mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 23:31:52 +08:00
Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product
This commit is contained in:
commit
c9c176ea05
@ -160,12 +160,11 @@
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|------|---------------------------|
|
||||
| 🚀 | 商户信息 | 管理商户信息,支持 Saas 场景下的多商户功能 |
|
||||
| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 |
|
||||
| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 |
|
||||
| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 |
|
||||
|
||||
ps:核心功能已经实现,正在对接微信小程序中...
|
||||
| 🚀 | 回调通知 | 查看支付回调业务的【支付】【退款】的通知结果 |
|
||||
| 🚀 | 接入示例 | 提供接入支付系统的【支付】【退款】的功能实战 |
|
||||
|
||||
### 基础设施
|
||||
|
||||
|
2
pom.xml
2
pom.xml
@ -20,7 +20,7 @@
|
||||
<!-- <module>yudao-module-bpm</module>-->
|
||||
<!-- <module>yudao-module-report</module>-->
|
||||
<!-- <module>yudao-module-mp</module>-->
|
||||
<module>yudao-module-mall</module>
|
||||
<!-- <module>yudao-module-mall</module>-->
|
||||
<!-- 示例项目 -->
|
||||
<module>yudao-example</module>
|
||||
</modules>
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,174 +0,0 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : docer-master-root(3308)
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 80030
|
||||
Source Host : 10.211.55.5:3308
|
||||
Source Schema : mall
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 80030
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 28/06/2023 22:40:52
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for member_point_config
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `member_point_config`;
|
||||
CREATE TABLE `member_point_config` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
|
||||
`trade_deduct_enable` bit(1) DEFAULT NULL COMMENT '1 开启积分抵扣\n0 关闭积分抵扣',
|
||||
`trade_deduct_unit_price` int DEFAULT NULL COMMENT '积分抵扣(单位:分)',
|
||||
`trade_deduct_max_price` int DEFAULT NULL COMMENT '积分抵扣最大值',
|
||||
`trade_give_point` bigint DEFAULT NULL COMMENT '1元赠送多少分',
|
||||
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新人',
|
||||
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',
|
||||
`tenant_id` varchar(255) DEFAULT NULL COMMENT '租户id',
|
||||
`deleted` bit(1) DEFAULT b'0' COMMENT '是否被删除 0 未删除 1已删除',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员积分配置表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of member_point_config
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `member_point_config` (`id`, `trade_deduct_enable`, `trade_deduct_unit_price`, `trade_deduct_max_price`, `trade_give_point`, `creator`, `create_time`, `updater`, `update_time`, `tenant_id`, `deleted`) VALUES (1, b'1', 0, 10000, 1, '1', '2023-06-10 10:57:22', '1', '2023-06-10 03:06:58', '1', b'1');
|
||||
INSERT INTO `member_point_config` (`id`, `trade_deduct_enable`, `trade_deduct_unit_price`, `trade_deduct_max_price`, `trade_give_point`, `creator`, `create_time`, `updater`, `update_time`, `tenant_id`, `deleted`) VALUES (2, b'1', 32, 10003, 1212, '1', '2023-06-10 11:07:12', '1', '2023-06-28 21:50:34', '1', b'0');
|
||||
INSERT INTO `member_point_config` (`id`, `trade_deduct_enable`, `trade_deduct_unit_price`, `trade_deduct_max_price`, `trade_give_point`, `creator`, `create_time`, `updater`, `update_time`, `tenant_id`, `deleted`) VALUES (3, b'1', 12, 12, 12, '1', '2023-06-10 16:09:26', '1', '2023-06-10 08:10:53', '1', b'1');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for member_point_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `member_point_record`;
|
||||
CREATE TABLE `member_point_record` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
|
||||
`biz_id` varchar(255) DEFAULT NULL COMMENT '业务编码',
|
||||
`biz_type` varchar(255) DEFAULT NULL COMMENT '业务类型',
|
||||
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '1增加 0扣减',
|
||||
`title` varchar(255) DEFAULT NULL COMMENT '积分标题',
|
||||
`description` varchar(5000) DEFAULT NULL COMMENT '积分描述',
|
||||
`point` int DEFAULT NULL COMMENT '积分',
|
||||
`total_point` int NOT NULL COMMENT '变动后的积分',
|
||||
`status` int DEFAULT NULL COMMENT '状态:1-订单创建,2-冻结期,3-完成,4-失效(订单退款)\n',
|
||||
`user_id` int DEFAULT NULL COMMENT '用户id',
|
||||
`freezing_time` datetime DEFAULT NULL COMMENT '冻结时间',
|
||||
`thawing_time` datetime DEFAULT NULL COMMENT '解冻时间',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '发生时间',
|
||||
`tenant_id` varchar(255) DEFAULT NULL COMMENT '租户',
|
||||
`deleted` int DEFAULT '0' COMMENT '是否删除',
|
||||
`creator` varchar(255) DEFAULT NULL COMMENT '创建用户',
|
||||
`updater` varchar(255) DEFAULT NULL COMMENT '更新用户',
|
||||
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `index_userId` (`user_id`),
|
||||
KEY `index_title` (`title`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户积分记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of member_point_record
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `member_point_record` (`id`, `biz_id`, `biz_type`, `type`, `title`, `description`, `point`, `total_point`, `status`, `user_id`, `freezing_time`, `thawing_time`, `create_time`, `tenant_id`, `deleted`, `creator`, `updater`, `update_time`) VALUES (1, '1', '1', '1', '12', NULL, 212, 12, 1, 12, '2023-06-13 00:00:00', '2023-06-20 00:00:00', '2023-06-10 12:38:48', '1', 1, '1', '1', '2023-06-10 04:42:24');
|
||||
INSERT INTO `member_point_record` (`id`, `biz_id`, `biz_type`, `type`, `title`, `description`, `point`, `total_point`, `status`, `user_id`, `freezing_time`, `thawing_time`, `create_time`, `tenant_id`, `deleted`, `creator`, `updater`, `update_time`) VALUES (2, '12', '1', '0', NULL, NULL, 1212, 12, 2, 12, '2023-06-28 00:00:00', NULL, '2023-06-10 12:42:48', '1', 0, '1', '1', '2023-06-10 12:43:04');
|
||||
INSERT INTO `member_point_record` (`id`, `biz_id`, `biz_type`, `type`, `title`, `description`, `point`, `total_point`, `status`, `user_id`, `freezing_time`, `thawing_time`, `create_time`, `tenant_id`, `deleted`, `creator`, `updater`, `update_time`) VALUES (3, '12', '1', '1', '12', NULL, 12, 12, 1, 12, '2023-06-27 00:00:00', '2023-06-23 00:00:00', '2023-06-10 20:06:48', '1', 0, '1', '1', '2023-06-10 20:06:48');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for member_sign_in_config
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `member_sign_in_config`;
|
||||
CREATE TABLE `member_sign_in_config` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '规则自增主键',
|
||||
`day` int DEFAULT NULL COMMENT '签到第x天',
|
||||
`point` int DEFAULT NULL COMMENT '签到天数对应分数',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',
|
||||
`tenant_id` varchar(255) DEFAULT NULL COMMENT '租户id',
|
||||
`deleted` int DEFAULT '0' COMMENT '是否删除',
|
||||
`creator` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`updater` varchar(255) DEFAULT NULL COMMENT '变更人',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='积分签到规则';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of member_sign_in_config
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (1, 1, 10, '2023-06-10 11:34:43', '2023-06-10 11:34:43', '1', 0, '1', '1');
|
||||
INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (2, 2, 20, '2023-06-10 11:34:59', '2023-06-10 03:55:35', '1', 1, '1', '1');
|
||||
INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (3, 7, 1001, '2023-06-10 17:47:45', '2023-06-10 19:54:37', '1', 0, '1', '1');
|
||||
INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (4, 6, 12121, '2023-06-10 17:47:55', '2023-06-10 19:48:37', '1', 0, '1', '1');
|
||||
INSERT INTO `member_sign_in_config` (`id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (5, 2, 12, '2023-06-10 19:54:52', '2023-06-10 19:54:52', '1', 0, '1', '1');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for member_sign_in_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `member_sign_in_record`;
|
||||
CREATE TABLE `member_sign_in_record` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '签到自增id',
|
||||
`user_id` int DEFAULT NULL COMMENT '签到用户',
|
||||
`day` int DEFAULT NULL COMMENT '第几天签到',
|
||||
`point` int DEFAULT NULL COMMENT '签到的分数',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '签到时间',
|
||||
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',
|
||||
`tenant_id` varchar(255) DEFAULT NULL COMMENT '租户id',
|
||||
`deleted` int DEFAULT '0' COMMENT '是否删除',
|
||||
`creator` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`updater` varchar(255) DEFAULT NULL COMMENT '更新人',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户签到积分';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of member_sign_in_record
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (1, 121, 1, 123, '2023-06-10 12:58:18', '2023-06-10 04:59:00', '1', 1, '1', '1');
|
||||
INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (2, 12, 12, 12, '2023-06-10 19:56:39', '2023-06-10 11:56:45', '1', 1, '1', '1');
|
||||
INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (3, 12, 12, 1212, '2023-06-10 20:01:17', '2023-06-10 12:01:23', '1', 1, '1', '1');
|
||||
INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (4, 12, 12, 1212, '2023-06-10 20:01:27', '2023-06-10 20:01:27', '1', 0, '1', '1');
|
||||
COMMIT;
|
||||
|
||||
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (170, '积分业务类型', 'member_point_biz_type', 0, '', '1', '2023-06-10 12:15:00', '1', '2023-06-28 13:48:20', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (171, '积分订单状态', 'member_point_status', 0, '', '1', '2023-06-10 12:16:27', '1', '2023-06-28 13:48:17', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (169, '是否抵扣积分', 'trade_deduct_enable', 0, NULL, '1', '2023-06-10 00:34:12', '1', '2023-06-10 04:14:20', b'1', '2023-06-10 12:14:20');
|
||||
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1235, 1, '购物', '1', 'member_point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:27', '1', '2023-06-28 13:48:28', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1236, 2, '签到', '2', 'member_point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:48', '1', '2023-06-28 13:48:31', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1237, 1, '订单创建', '1', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:16:42', '1', '2023-06-28 13:48:34', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1238, 2, '冻结期', '2', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:16:58', '1', '2023-06-28 13:48:36', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1239, 3, '完成', '3', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:17:07', '1', '2023-06-28 13:48:38', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1240, 4, '失效(订单退款)', '4', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:17:21', '1', '2023-06-28 13:48:42', b'0');
|
||||
|
||||
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2162, '会员中心', '', 1, 55, 0, '/member', 'date-range', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-06-10 00:42:03', '1', '2023-06-28 21:52:34', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2175, '积分配置', '', 2, 0, 2199, 'config', '', 'member/point/config/index', 'PointConfig', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 22:50:59', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2176, '积分设置查询', 'point:config:query', 3, 1, 2175, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '', '2023-06-10 02:07:44', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2177, '积分设置创建', 'point:config:save', 3, 2, 2175, '', '', '', '', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 20:32:31', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2181, '签到配置', '', 2, 2, 2200, 'sign-in-config', '', 'member/signin/config/index', 'SignInConfig', 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '1', '2023-06-27 22:51:45', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2182, '积分签到规则查询', 'point:sign-in-config:query', 3, 1, 2181, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2183, '积分签到规则创建', 'point:sign-in-config:create', 3, 2, 2181, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2184, '积分签到规则更新', 'point:sign-in-config:update', 3, 3, 2181, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2185, '积分签到规则删除', 'point:sign-in-config:delete', 3, 4, 2181, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2186, '积分签到规则导出', 'point:sign-in-config:export', 3, 5, 2181, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2187, '积分记录', '', 2, 1, 2199, 'record', '', 'member/point/record/index', 'PointRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '1', '2023-06-27 22:51:07', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2188, '用户积分记录查询', 'point:record:query', 3, 1, 2187, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '', '2023-06-10 04:18:50', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2192, '用户积分记录导出', 'point:record:export', 3, 5, 2187, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '', '2023-06-10 04:18:50', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2193, '签到记录', '', 2, 3, 2200, 'sign-in-record', '', 'member/signin/record/index', 'SignInRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '1', '2023-06-27 22:51:54', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2194, '用户签到积分查询', 'point:sign-in-record:query', 3, 1, 2193, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2197, '用户签到积分删除', 'point:sign-in-record:delete', 3, 4, 2193, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2198, '用户签到积分导出', 'point:sign-in-record:export', 3, 5, 2193, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2199, '会员积分', '', 1, 1, 2162, 'point', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:48:51', '1', '2023-06-27 22:48:51', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2200, '会员签到', '', 1, 2, 2162, 'signin', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:49:53', '1', '2023-06-27 22:49:53', b'0');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
File diff suppressed because one or more lines are too long
@ -1,44 +0,0 @@
|
||||
-- ----------------------------
|
||||
-- 支付-会员钱包表
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pay_member_wallet`;
|
||||
CREATE TABLE `pay_member_wallet`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`user_id` bigint NOT NULL COMMENT '用户 id',
|
||||
`balance` int NOT NULL DEFAULT 0 COMMENT '余额, 单位分',
|
||||
`total_spending` int NOT NULL DEFAULT 0 COMMENT '累计支出, 单位分',
|
||||
`total_top_up` int NOT NULL DEFAULT 0 COMMENT '累计充值, 单位分',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB COMMENT='会员钱包表';
|
||||
|
||||
-- ----------------------------
|
||||
-- 支付-会员钱包明细表
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pay_member_wallet_transaction`;
|
||||
CREATE TABLE `pay_member_wallet_transaction`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`wallet_id` bigint NOT NULL COMMENT '会员钱包 id',
|
||||
`user_id` bigint NOT NULL COMMENT '用户 id',
|
||||
`trade_no` varchar(64) COMMENT '交易单号',
|
||||
`category` tinyint NOT NULL COMMENT '交易大类',
|
||||
`operate_type` tinyint NOT NULL COMMENT '操作分类',
|
||||
`operate_desc` varchar(64) NOT NULL COMMENT '操作说明',
|
||||
`amount` int NOT NULL COMMENT '交易金额, 单位分',
|
||||
`balance` int NOT NULL COMMENT '余额, 单位分',
|
||||
`mark` varchar(512) COMMENT '备注',
|
||||
`transaction_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '交易时间',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB COMMENT='会员钱包明细表';
|
@ -11,7 +11,7 @@
|
||||
Target Server Version : 80026
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 09/07/2023 20:25:37
|
||||
Date: 24/07/2023 08:51:31
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@ -73,6 +73,9 @@ CREATE TABLE `QRTZ_CRON_TRIGGERS` (
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai');
|
||||
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
|
||||
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
|
||||
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -133,6 +136,9 @@ CREATE TABLE `QRTZ_JOB_DETAILS` (
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000057400104A4F425F48414E444C45525F4E414D4574000C7061794E6F746966794A6F627800);
|
||||
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000127400104A4F425F48414E444C45525F4E414D457400117061794F726465724578706972654A6F627800);
|
||||
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000117400104A4F425F48414E444C45525F4E414D4574000F7061794F7264657253796E634A6F627800);
|
||||
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000137400104A4F425F48414E444C45525F4E414D45740010706179526566756E6453796E634A6F627800);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -185,7 +191,7 @@ CREATE TABLE `QRTZ_SCHEDULER_STATE` (
|
||||
-- Records of QRTZ_SCHEDULER_STATE
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai1677076619095', 1677076631456, 15000);
|
||||
INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai1690117495401', 1690119854263, 15000);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -279,202 +285,10 @@ CREATE TABLE `QRTZ_TRIGGERS` (
|
||||
-- Records of QRTZ_TRIGGERS
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1677076638000, 1677076637000, 5, 'WAITING', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for bpm_form
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `bpm_form`;
|
||||
CREATE TABLE `bpm_form` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '表单名',
|
||||
`status` tinyint NOT NULL COMMENT '开启状态',
|
||||
`conf` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '表单的配置',
|
||||
`fields` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '表单项的数组',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_form
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for bpm_oa_leave
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `bpm_oa_leave`;
|
||||
CREATE TABLE `bpm_oa_leave` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '请假表单主键',
|
||||
`user_id` bigint NOT NULL COMMENT '申请人的用户编号',
|
||||
`type` tinyint NOT NULL COMMENT '请假类型',
|
||||
`reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请假原因',
|
||||
`start_time` datetime NOT NULL COMMENT '开始时间',
|
||||
`end_time` datetime NOT NULL COMMENT '结束时间',
|
||||
`day` tinyint NOT NULL COMMENT '请假天数',
|
||||
`result` tinyint NOT NULL COMMENT '请假结果',
|
||||
`process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '流程实例的编号',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 35 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_oa_leave
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for bpm_process_definition_ext
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `bpm_process_definition_ext`;
|
||||
CREATE TABLE `bpm_process_definition_ext` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
|
||||
`model_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程模型的编号',
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '描述',
|
||||
`form_type` tinyint NOT NULL COMMENT '表单类型',
|
||||
`form_id` bigint NULL DEFAULT NULL COMMENT '表单编号',
|
||||
`form_conf` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '表单的配置',
|
||||
`form_fields` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '表单项的数组',
|
||||
`form_custom_create_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '自定义表单的提交路径',
|
||||
`form_custom_view_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '自定义表单的查看路径',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 141 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_process_definition_ext
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for bpm_process_instance_ext
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `bpm_process_instance_ext`;
|
||||
CREATE TABLE `bpm_process_instance_ext` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`start_user_id` bigint NOT NULL COMMENT '发起流程的用户编号',
|
||||
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '流程实例的名字',
|
||||
`process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程实例的编号',
|
||||
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
|
||||
`category` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '流程分类',
|
||||
`status` tinyint NOT NULL COMMENT '流程实例的状态',
|
||||
`result` tinyint NOT NULL COMMENT '流程实例的结果',
|
||||
`end_time` datetime NULL DEFAULT NULL COMMENT '结束时间',
|
||||
`form_variables` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '表单值',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 296 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_process_instance_ext
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for bpm_task_assign_rule
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `bpm_task_assign_rule`;
|
||||
CREATE TABLE `bpm_task_assign_rule` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`model_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程模型的编号',
|
||||
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
|
||||
`task_definition_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程任务定义的 key',
|
||||
`type` tinyint NOT NULL COMMENT '规则类型',
|
||||
`options` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '规则值,JSON 数组',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 276 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_task_assign_rule
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for bpm_task_ext
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `bpm_task_ext`;
|
||||
CREATE TABLE `bpm_task_ext` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`assignee_user_id` bigint NULL DEFAULT NULL COMMENT '任务的审批人',
|
||||
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '任务的名字',
|
||||
`task_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '任务的编号',
|
||||
`result` tinyint NOT NULL COMMENT '任务的结果',
|
||||
`reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '审批建议',
|
||||
`end_time` datetime NULL DEFAULT NULL COMMENT '任务的结束时间',
|
||||
`process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程实例的编号',
|
||||
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 351 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_task_ext
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for bpm_user_group
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `bpm_user_group`;
|
||||
CREATE TABLE `bpm_user_group` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '组名',
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '描述',
|
||||
`member_user_ids` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '成员编号数组',
|
||||
`status` tinyint NOT NULL COMMENT '状态(0正常 1停用)',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 113 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_user_group
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1688907102000, 1688907101000, 5, 'PAUSED', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
|
||||
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', 'payOrderExpireJob', 'DEFAULT', NULL, 1690011600000, -1, 5, 'PAUSED', 'CRON', 1690011553000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
|
||||
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', 'payOrderSyncJob', 'DEFAULT', NULL, 1690011600000, 1690011540000, 5, 'PAUSED', 'CRON', 1690007785000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
|
||||
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', 'payRefundSyncJob', 'DEFAULT', NULL, 1690117560000, 1690117500000, 5, 'PAUSED', 'CRON', 1690117424000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -546,7 +360,7 @@ CREATE TABLE `infra_api_error_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1291 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1391 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_api_error_log
|
||||
@ -584,7 +398,7 @@ CREATE TABLE `infra_codegen_column` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1698 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1715 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_codegen_column
|
||||
@ -617,7 +431,7 @@ CREATE TABLE `infra_codegen_table` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 131 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 132 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_codegen_table
|
||||
@ -782,14 +596,17 @@ CREATE TABLE `infra_job` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_job
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 1, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2022-11-24 23:01:35', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2023-07-09 20:51:41', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (16, 'Job 示例', 1, 'demoJob', NULL, '* * * L * ?', 1, 1, 0, '1', '2022-09-24 22:31:41', '1', '2022-09-24 22:31:42', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (17, '支付订单同步 Job', 2, 'payOrderSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 14:36:26', '1', '2023-07-22 15:39:08', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (18, '支付订单过期 Job', 2, 'payOrderExpireJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 15:36:23', '1', '2023-07-22 15:39:54', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (19, '退款订单的同步 Job', 2, 'payRefundSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-23 21:03:44', '1', '2023-07-23 21:09:00', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -813,7 +630,7 @@ CREATE TABLE `infra_job_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 161 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_job_log
|
||||
@ -936,7 +753,7 @@ CREATE TABLE `system_dict_data` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1341 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1348 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_dict_data
|
||||
@ -1012,33 +829,22 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (86, 0, '病假', '1', 'bpm_oa_leave_type', 0, 'primary', '', NULL, '1', '2021-09-21 22:35:28', '1', '2022-02-16 10:00:41', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (87, 1, '事假', '2', 'bpm_oa_leave_type', 0, 'info', '', NULL, '1', '2021-09-21 22:36:11', '1', '2022-02-16 10:00:49', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (88, 2, '婚假', '3', 'bpm_oa_leave_type', 0, 'warning', '', NULL, '1', '2021-09-21 22:36:38', '1', '2022-02-16 10:00:53', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (98, 1, 'v2', 'v2', 'pay_channel_wechat_version', 0, '', '', 'v2版本', '1', '2021-11-08 17:00:58', '1', '2021-11-08 17:00:58', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (99, 2, 'v3', 'v3', 'pay_channel_wechat_version', 0, '', '', 'v3版本', '1', '2021-11-08 17:01:07', '1', '2021-11-08 17:01:07', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (108, 1, 'RSA2', 'RSA2', 'pay_channel_alipay_sign_type', 0, '', '', 'RSA2', '1', '2021-11-18 15:39:29', '1', '2021-11-18 15:39:29', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (109, 1, '公钥模式', '1', 'pay_channel_alipay_mode', 0, '', '', '公钥模式:privateKey + alipayPublicKey', '1', '2021-11-18 15:45:23', '1', '2021-11-18 15:45:23', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (110, 2, '证书模式', '2', 'pay_channel_alipay_mode', 0, '', '', '证书模式:appCertContent + alipayPublicCertContent + rootCertContent', '1', '2021-11-18 15:45:40', '1', '2021-11-18 15:45:40', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (111, 1, '线上', 'https://openapi.alipay.com/gateway.do', 'pay_channel_alipay_server_type', 0, '', '', '网关地址 - 线上', '1', '2021-11-18 16:59:32', '1', '2021-11-21 17:37:29', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (112, 2, '沙箱', 'https://openapi.alipaydev.com/gateway.do', 'pay_channel_alipay_server_type', 0, '', '', '网关地址 - 沙箱', '1', '2021-11-18 16:59:48', '1', '2021-11-21 17:37:39', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (113, 1, '微信 JSAPI 支付', 'wx_pub', 'pay_channel_code_type', 0, '', '', '微信 JSAPI(公众号) 支付', '1', '2021-12-03 10:40:24', '1', '2021-12-04 16:41:00', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (114, 2, '微信小程序支付', 'wx_lite', 'pay_channel_code_type', 0, '', '', '微信小程序支付', '1', '2021-12-03 10:41:06', '1', '2021-12-03 10:41:06', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (115, 3, '微信 App 支付', 'wx_app', 'pay_channel_code_type', 0, '', '', '微信 App 支付', '1', '2021-12-03 10:41:20', '1', '2021-12-03 10:41:20', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (116, 4, '支付宝 PC 网站支付', 'alipay_pc', 'pay_channel_code_type', 0, '', '', '支付宝 PC 网站支付', '1', '2021-12-03 10:42:09', '1', '2021-12-03 10:42:09', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (117, 5, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code_type', 0, '', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2021-12-03 10:42:26', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (118, 6, '支付宝App 支付', 'alipay_app', 'pay_channel_code_type', 0, '', '', '支付宝App 支付', '1', '2021-12-03 10:42:55', '1', '2021-12-03 10:42:55', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (119, 7, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code_type', 0, '', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2021-12-03 10:43:10', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (120, 1, '通知成功', '10', 'pay_order_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2022-02-16 13:59:13', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, 2, '通知失败', '20', 'pay_order_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2022-02-16 13:59:17', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, 3, '未通知', '0', 'pay_order_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2022-02-16 13:59:23', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (123, 1, '支付成功', '10', 'pay_order_status', 0, 'success', '', '支付成功', '1', '2021-12-03 11:18:29', '1', '2022-02-16 15:24:25', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (124, 2, '支付关闭', '20', 'pay_order_status', 0, 'danger', '', '支付关闭', '1', '2021-12-03 11:18:42', '1', '2022-02-16 15:24:31', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (125, 3, '未支付', '0', 'pay_order_status', 0, 'info', '', '未支付', '1', '2021-12-03 11:18:18', '1', '2022-02-16 15:24:35', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (126, 1, '未退款', '0', 'pay_order_refund_status', 0, '', '', '未退款', '1', '2021-12-03 11:30:35', '1', '2021-12-03 11:34:05', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (127, 2, '部分退款', '10', 'pay_order_refund_status', 0, '', '', '部分退款', '1', '2021-12-03 11:30:44', '1', '2021-12-03 11:34:10', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (128, 3, '全部退款', '20', 'pay_order_refund_status', 0, '', '', '全部退款', '1', '2021-12-03 11:30:52', '1', '2021-12-03 11:34:14', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1117, 1, '退款订单生成', '0', 'pay_refund_order_status', 0, 'primary', '', '退款订单生成', '1', '2021-12-10 16:44:44', '1', '2022-02-16 14:05:24', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, 2, '退款成功', '1', 'pay_refund_order_status', 0, 'success', '', '退款成功', '1', '2021-12-10 16:44:59', '1', '2022-02-16 14:05:28', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, 3, '退款失败', '2', 'pay_refund_order_status', 0, 'danger', '', '退款失败', '1', '2021-12-10 16:45:10', '1', '2022-02-16 14:05:34', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1124, 8, '退款关闭', '99', 'pay_refund_order_status', 0, 'info', '', '退款关闭', '1', '2021-12-10 16:46:26', '1', '2022-02-16 14:05:40', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (113, 1, '微信公众号支付', 'wx_pub', 'pay_channel_code', 0, 'success', '', '微信公众号支付', '1', '2021-12-03 10:40:24', '1', '2023-07-19 20:08:47', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (114, 2, '微信小程序支付', 'wx_lite', 'pay_channel_code', 0, 'success', '', '微信小程序支付', '1', '2021-12-03 10:41:06', '1', '2023-07-19 20:08:50', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (115, 3, '微信 App 支付', 'wx_app', 'pay_channel_code', 0, 'success', '', '微信 App 支付', '1', '2021-12-03 10:41:20', '1', '2023-07-19 20:08:56', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (116, 10, '支付宝 PC 网站支付', 'alipay_pc', 'pay_channel_code', 0, 'primary', '', '支付宝 PC 网站支付', '1', '2021-12-03 10:42:09', '1', '2023-07-19 20:09:12', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (123, 10, '支付成功', '10', 'pay_order_status', 0, 'success', '', '支付成功', '1', '2021-12-03 11:18:29', '1', '2023-07-19 18:04:28', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (124, 30, '支付关闭', '30', 'pay_order_status', 0, 'info', '', '支付关闭', '1', '2021-12-03 11:18:42', '1', '2023-07-19 18:05:07', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (125, 0, '等待支付', '0', 'pay_order_status', 0, 'info', '', '未支付', '1', '2021-12-03 11:18:18', '1', '2023-07-19 18:04:15', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, 0, '等待退款', '0', 'pay_refund_status', 0, 'info', '', '等待退款', '1', '2021-12-10 16:44:59', '1', '2023-07-19 10:14:39', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, 20, '退款失败', '20', 'pay_refund_status', 0, 'danger', '', '退款失败', '1', '2021-12-10 16:45:10', '1', '2023-07-19 10:15:10', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1124, 10, '退款成功', '10', 'pay_refund_status', 0, 'success', '', '退款成功', '1', '2021-12-10 16:46:26', '1', '2023-07-19 10:15:00', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1125, 0, '默认', '1', 'bpm_model_category', 0, 'primary', '', '流程分类 - 默认', '1', '2022-01-02 08:41:11', '1', '2022-02-16 20:01:42', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1126, 0, 'OA', '2', 'bpm_model_category', 0, 'success', '', '流程分类 - OA', '1', '2022-01-02 08:41:22', '1', '2022-02-16 20:01:50', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1127, 0, '进行中', '1', 'bpm_process_instance_status', 0, 'primary', '', '流程实例的状态 - 进行中', '1', '2022-01-07 23:47:22', '1', '2022-02-16 20:07:49', b'0');
|
||||
@ -1061,9 +867,6 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1144, 21, '流程发起人的二级领导', '21', 'bpm_task_assign_script', 0, '', '', '任务分配自定义脚本 - 流程发起人的二级领导', '103', '2022-01-15 21:24:46', '103', '2022-01-15 21:24:57', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1145, 1, '管理后台', '1', 'infra_codegen_scene', 0, '', '', '代码生成的场景枚举 - 管理后台', '1', '2022-02-02 13:15:06', '1', '2022-03-10 16:32:59', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1146, 2, '用户 APP', '2', 'infra_codegen_scene', 0, '', '', '代码生成的场景枚举 - 用户 APP', '1', '2022-02-02 13:15:19', '1', '2022-03-10 16:33:03', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1147, 0, '未退款', '0', 'pay_refund_order_type', 0, 'info', '', '退款类型 - 未退款', '1', '2022-02-16 14:09:01', '1', '2022-02-16 14:09:01', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1148, 10, '部分退款', '10', 'pay_refund_order_type', 0, 'success', '', '退款类型 - 部分退款', '1', '2022-02-16 14:09:25', '1', '2022-02-16 14:11:38', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1149, 20, '全部退款', '20', 'pay_refund_order_type', 0, 'warning', '', '退款类型 - 全部退款', '1', '2022-02-16 14:11:33', '1', '2022-02-16 14:11:33', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1150, 1, '数据库', '1', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:25:28', '1', '2022-03-15 00:25:28', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1151, 10, '本地磁盘', '10', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:25:41', '1', '2022-03-15 00:25:56', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1152, 11, 'FTP 服务器', '11', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:26:06', '1', '2022-03-15 00:26:10', b'0');
|
||||
@ -1142,8 +945,8 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1226, 30, '不发送', '30', 'system_mail_send_status', 0, 'info', '', '邮件发送状态 - 不发送', '1', '2023-01-26 09:55:06', '1', '2023-01-26 16:36:36', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1227, 1, '通知公告', '1', 'system_notify_template_type', 0, 'primary', '', '站内信模版的类型 - 通知公告', '1', '2023-01-28 10:35:59', '1', '2023-01-28 10:35:59', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1228, 2, '系统消息', '2', 'system_notify_template_type', 0, 'success', '', '站内信模版的类型 - 系统消息', '1', '2023-01-28 10:36:20', '1', '2023-01-28 10:36:25', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1229, 0, '模拟支付', 'mock', 'pay_channel_code_type', 0, 'default', '', NULL, '1', '2023-02-12 21:50:22', '1', '2023-02-12 21:50:22', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1230, 8, '支付宝条码支付', 'alipay_bar', 'pay_channel_code_type', 0, 'default', '', NULL, '1', '2023-02-18 23:32:24', '1', '2023-02-18 23:32:32', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1229, 0, '模拟支付', 'mock', 'pay_channel_code', 0, 'default', '', '模拟支付', '1', '2023-02-12 21:50:22', '1', '2023-07-10 10:11:02', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1230, 13, '支付宝条码支付', 'alipay_bar', 'pay_channel_code', 0, 'primary', '', '支付宝条码支付', '1', '2023-02-18 23:32:24', '1', '2023-07-19 20:09:23', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1231, 10, 'Vue2 Element UI 标准模版', '10', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:03:55', '1', '2023-04-13 00:03:55', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1232, 20, 'Vue3 Element Plus 标准模版', '20', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:08', '1', '2023-04-13 00:04:08', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1233, 21, 'Vue3 Element Plus Schema 模版', '21', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:26', '1', '2023-04-13 00:04:26', b'0');
|
||||
@ -1166,6 +969,13 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1338, 2, '冻结期', '2', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:16:58', '1', '2023-06-28 13:48:36', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1339, 3, '完成', '3', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:17:07', '1', '2023-06-28 13:48:38', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1340, 4, '失效(订单退款)', '4', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:17:21', '1', '2023-06-28 13:48:42', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1341, 20, '已退款', '20', 'pay_order_status', 0, 'danger', '', '已退款', '1', '2023-07-19 18:05:37', '1', '2023-07-19 18:05:37', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1342, 21, '请求成功,但是结果失败', '21', 'pay_notify_status', 0, 'warning', '', '请求成功,但是结果失败', '1', '2023-07-19 18:10:47', '1', '2023-07-19 18:11:38', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1343, 22, '请求失败', '22', 'pay_notify_status', 0, 'warning', '', NULL, '1', '2023-07-19 18:11:05', '1', '2023-07-19 18:11:27', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1344, 4, '微信扫码支付', 'wx_native', 'pay_channel_code', 0, 'success', '', '微信扫码支付', '1', '2023-07-19 20:07:47', '1', '2023-07-19 20:09:03', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1345, 5, '微信条码支付', 'wx_bar', 'pay_channel_code', 0, 'success', '', '微信条码支付\n', '1', '2023-07-19 20:08:06', '1', '2023-07-19 20:09:08', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1346, 1, '支付单', '1', 'pay_notify_type', 0, 'primary', '', '支付单', '1', '2023-07-20 12:23:17', '1', '2023-07-20 12:23:17', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1347, 2, '退款单', '2', 'pay_notify_type', 0, 'danger', '', NULL, '1', '2023-07-20 12:23:26', '1', '2023-07-20 12:23:26', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -1186,7 +996,7 @@ CREATE TABLE `system_dict_type` (
|
||||
`deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 173 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 174 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_dict_type
|
||||
@ -1212,16 +1022,10 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (115, '错误码的类型', 'system_error_code_type', 0, NULL, '1', '2021-04-21 00:06:30', '1', '2022-02-01 16:36:49', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (116, '登陆日志的类型', 'system_login_type', 0, '登陆日志的类型', '1', '2021-10-06 00:50:46', '1', '2022-02-01 16:35:56', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (117, 'OA 请假类型', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:34:33', '1', '2022-01-22 10:41:37', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (122, '支付渠道微信版本', 'pay_channel_wechat_version', 0, '支付渠道微信版本', '1', '2021-11-08 17:00:26', '1', '2021-11-08 17:00:26', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (127, '支付渠道支付宝算法类型', 'pay_channel_alipay_sign_type', 0, '支付渠道支付宝算法类型', '1', '2021-11-18 15:39:09', '1', '2021-11-18 15:39:09', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (128, '支付渠道支付宝公钥类型', 'pay_channel_alipay_mode', 0, '支付渠道支付宝公钥类型', '1', '2021-11-18 15:44:28', '1', '2021-11-18 15:44:28', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (129, '支付宝网关地址', 'pay_channel_alipay_server_type', 0, '支付宝网关地址', '1', '2021-11-18 16:58:55', '1', '2021-11-18 17:01:34', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (130, '支付渠道编码类型', 'pay_channel_code_type', 0, '支付渠道的编码', '1', '2021-12-03 10:35:08', '1', '2021-12-03 10:35:08', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (131, '支付订单回调状态', 'pay_order_notify_status', 0, '支付订单回调状态', '1', '2021-12-03 10:53:29', '1', '2021-12-03 10:53:29', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (130, '支付渠道编码类型', 'pay_channel_code', 0, '支付渠道的编码', '1', '2021-12-03 10:35:08', '1', '2023-07-10 10:11:39', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (131, '支付回调状态', 'pay_notify_status', 0, '支付回调状态(包括退款回调)', '1', '2021-12-03 10:53:29', '1', '2023-07-19 18:09:43', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (132, '支付订单状态', 'pay_order_status', 0, '支付订单状态', '1', '2021-12-03 11:17:50', '1', '2021-12-03 11:17:50', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (133, '支付订单退款状态', 'pay_order_refund_status', 0, '支付订单退款状态', '1', '2021-12-03 11:27:31', '1', '2021-12-03 11:27:31', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (134, '退款订单状态', 'pay_refund_order_status', 0, '退款订单状态', '1', '2021-12-10 16:42:50', '1', '2021-12-10 16:42:50', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (135, '退款订单类别', 'pay_refund_order_type', 0, '退款订单类别', '1', '2021-12-10 17:14:53', '1', '2021-12-10 17:14:53', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (134, '退款订单状态', 'pay_refund_status', 0, '退款订单状态', '1', '2021-12-10 16:42:50', '1', '2023-07-19 10:13:17', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (138, '流程分类', 'bpm_model_category', 0, '流程分类', '1', '2022-01-02 08:40:45', '1', '2022-01-02 08:40:45', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (139, '流程实例的状态', 'bpm_process_instance_status', 0, '流程实例的状态', '1', '2022-01-07 23:46:42', '1', '2022-01-07 23:46:42', b'0', NULL);
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (140, '流程实例的结果', 'bpm_process_instance_result', 0, '流程实例的结果', '1', '2022-01-07 23:48:10', '1', '2022-01-07 23:48:10', b'0', NULL);
|
||||
@ -1256,6 +1060,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (170, '快递计费方式', 'trade_delivery_express_charge_mode', 0, '用于商城交易模块配送管理', '1', '2023-05-21 22:45:03', '1', '2023-05-21 22:45:03', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (171, '积分业务类型', 'member_point_biz_type', 0, '', '1', '2023-06-10 12:15:00', '1', '2023-06-28 13:48:20', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (172, '积分订单状态', 'member_point_status', 0, '', '1', '2023-06-10 12:16:27', '1', '2023-06-28 13:48:17', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (173, '支付通知类型', 'pay_notify_type', 0, NULL, '1', '2023-07-20 12:23:03', '1', '2023-07-20 12:23:03', b'0', '1970-01-01 00:00:00');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -1304,7 +1109,7 @@ CREATE TABLE `system_login_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2223 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2243 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_login_log
|
||||
@ -1434,7 +1239,7 @@ CREATE TABLE `system_menu` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2301 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2303 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_menu
|
||||
@ -1568,7 +1373,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, '请假查询', '', 2, 0, 5, 'leave', 'user', 'bpm/oa/leave/index', 'BpmOALeave', 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2023-04-08 11:30:40', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, '请假申请查询', 'bpm:oa-leave:query', 3, 1, 1118, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1120, '请假申请创建', 'bpm:oa-leave:create', 3, 2, 1118, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1126, '应用信息', '', 2, 1, 1117, 'app', 'table', 'pay/app/index', 'PayMerchant', 0, b'1', b'1', b'1', '', '2021-11-10 01:13:30', '1', '2023-04-08 10:43:14', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1126, '应用信息', '', 2, 1, 1117, 'app', 'table', 'pay/app/index', 'PayApp', 0, b'1', b'1', b'1', '', '2021-11-10 01:13:30', '1', '2023-07-20 12:13:32', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1127, '支付应用信息查询', 'pay:app:query', 3, 1, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1128, '支付应用信息创建', 'pay:app:create', 3, 2, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1129, '支付应用信息更新', 'pay:app:update', 3, 3, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
|
||||
@ -1846,6 +1651,8 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2297, '用户签到积分删除', 'point:sign-in-record:delete', 3, 4, 2293, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2299, '会员积分', '', 1, 1, 2262, 'point', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:48:51', '1', '2023-06-27 22:48:51', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2300, '会员签到', '', 1, 2, 2262, 'signin', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:49:53', '1', '2023-06-27 22:49:53', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2301, '回调通知', '', 2, 4, 1117, 'notify', 'example', 'pay/notify/index', 'PayNotify', 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '1', '2023-07-20 13:45:08', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -1962,7 +1769,7 @@ CREATE TABLE `system_oauth2_access_token` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2007 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2231 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_access_token
|
||||
@ -2084,7 +1891,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 785 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 804 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_refresh_token
|
||||
@ -2124,7 +1931,7 @@ CREATE TABLE `system_operate_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 6601 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 7134 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_operate_log
|
||||
@ -3415,7 +3222,7 @@ CREATE TABLE `system_users` (
|
||||
-- Records of system_users
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://test.yudao.iocoder.cn/e1fdd7271685ec143a0900681606406621717a666ad0b2798b096df41422b32f.png', 0, '127.0.0.1', '2023-07-09 12:19:37', 'admin', '2021-01-05 17:03:47', NULL, '2023-07-09 12:19:37', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://test.yudao.iocoder.cn/e1fdd7271685ec143a0900681606406621717a666ad0b2798b096df41422b32f.png', 0, '127.0.0.1', '2023-07-24 08:41:23', 'admin', '2021-01-05 17:03:47', NULL, '2023-07-24 08:41:23', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '127.0.0.1', '2022-05-28 15:43:17', '', '2021-01-21 02:13:53', NULL, '2022-07-09 09:00:33', b'0', 1);
|
||||
|
@ -27,7 +27,7 @@ public interface PayClient {
|
||||
* 调用支付渠道,统一下单
|
||||
*
|
||||
* @param reqDTO 下单信息
|
||||
* @return 各支付渠道的返回结果
|
||||
* @return 支付订单信息
|
||||
*/
|
||||
PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO);
|
||||
|
||||
@ -40,6 +40,14 @@ public interface PayClient {
|
||||
*/
|
||||
PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body);
|
||||
|
||||
/**
|
||||
* 获得支付订单信息
|
||||
*
|
||||
* @param outTradeNo 外部订单号
|
||||
* @return 支付订单信息
|
||||
*/
|
||||
PayOrderRespDTO getOrder(String outTradeNo);
|
||||
|
||||
// ============ 退款相关 ==========
|
||||
|
||||
/**
|
||||
@ -59,4 +67,13 @@ public interface PayClient {
|
||||
*/
|
||||
PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body);
|
||||
|
||||
/**
|
||||
* 获得退款订单信息
|
||||
*
|
||||
* @param outTradeNo 外部订单号
|
||||
* @param outRefundNo 外部退款号
|
||||
* @return 退款订单信息
|
||||
*/
|
||||
PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
|
||||
|
||||
}
|
||||
|
@ -94,38 +94,40 @@ public class PayOrderRespDTO {
|
||||
/**
|
||||
* 创建【SUCCESS】状态的订单返回
|
||||
*/
|
||||
public PayOrderRespDTO(String channelOrderNo, String channelUserId, LocalDateTime successTime,
|
||||
String outTradeNo, Object rawData) {
|
||||
this.status = PayOrderStatusRespEnum.SUCCESS.getStatus();
|
||||
this.channelOrderNo = channelOrderNo;
|
||||
this.channelUserId = channelUserId;
|
||||
this.successTime = successTime;
|
||||
public static PayOrderRespDTO successOf(String channelOrderNo, String channelUserId, LocalDateTime successTime,
|
||||
String outTradeNo, Object rawData) {
|
||||
PayOrderRespDTO respDTO = new PayOrderRespDTO();
|
||||
respDTO.status = PayOrderStatusRespEnum.SUCCESS.getStatus();
|
||||
respDTO.channelOrderNo = channelOrderNo;
|
||||
respDTO.channelUserId = channelUserId;
|
||||
respDTO.successTime = successTime;
|
||||
// 相对通用的字段
|
||||
this.outTradeNo = outTradeNo;
|
||||
this.rawData = rawData;
|
||||
respDTO.outTradeNo = outTradeNo;
|
||||
respDTO.rawData = rawData;
|
||||
return respDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建【SUCCESS】或【CLOSED】状态的订单返回,适合支付渠道回调时
|
||||
* 创建指定状态的订单返回,适合支付渠道回调时
|
||||
*/
|
||||
public PayOrderRespDTO(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime,
|
||||
String outTradeNo, Object rawData) {
|
||||
this.status = status;
|
||||
this.channelOrderNo = channelOrderNo;
|
||||
this.channelUserId = channelUserId;
|
||||
this.successTime = successTime;
|
||||
public static PayOrderRespDTO of(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime,
|
||||
String outTradeNo, Object rawData) {
|
||||
PayOrderRespDTO respDTO = new PayOrderRespDTO();
|
||||
respDTO.status = status;
|
||||
respDTO.channelOrderNo = channelOrderNo;
|
||||
respDTO.channelUserId = channelUserId;
|
||||
respDTO.successTime = successTime;
|
||||
// 相对通用的字段
|
||||
this.outTradeNo = outTradeNo;
|
||||
this.rawData = rawData;
|
||||
respDTO.outTradeNo = outTradeNo;
|
||||
respDTO.rawData = rawData;
|
||||
return respDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建【CLOSED】状态的订单返回,适合调用支付渠道失败时
|
||||
*
|
||||
* 参数和 {@link #PayOrderRespDTO(String, String, String, Object)} 冲突,所以独立个方法出来
|
||||
*/
|
||||
public static PayOrderRespDTO build(String channelErrorCode, String channelErrorMsg,
|
||||
String outTradeNo, Object rawData) {
|
||||
public static PayOrderRespDTO closedOf(String channelErrorCode, String channelErrorMsg,
|
||||
String outTradeNo, Object rawData) {
|
||||
PayOrderRespDTO respDTO = new PayOrderRespDTO();
|
||||
respDTO.status = PayOrderStatusRespEnum.CLOSED.getStatus();
|
||||
respDTO.channelErrorCode = channelErrorCode;
|
||||
|
@ -94,7 +94,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||
throws Throwable;
|
||||
|
||||
@Override
|
||||
public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
|
||||
public final PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
|
||||
try {
|
||||
return doParseOrderNotify(params, body);
|
||||
} catch (Throwable ex) {
|
||||
@ -107,10 +107,24 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||
protected abstract PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body)
|
||||
throws Throwable;
|
||||
|
||||
@Override
|
||||
public final PayOrderRespDTO getOrder(String outTradeNo) {
|
||||
try {
|
||||
return doGetOrder(outTradeNo);
|
||||
} catch (Throwable ex) {
|
||||
log.error("[getOrder][客户端({}) outTradeNo({}) 查询支付单异常]",
|
||||
getId(), outTradeNo, ex);
|
||||
throw buildPayException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract PayOrderRespDTO doGetOrder(String outTradeNo)
|
||||
throws Throwable;
|
||||
|
||||
// ============ 退款相关 ==========
|
||||
|
||||
@Override
|
||||
public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
|
||||
public final PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
|
||||
ValidationUtils.validate(reqDTO);
|
||||
// 执行统一退款
|
||||
PayRefundRespDTO resp;
|
||||
@ -131,7 +145,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||
protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable;
|
||||
|
||||
@Override
|
||||
public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
|
||||
public final PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
|
||||
try {
|
||||
return doParseRefundNotify(params, body);
|
||||
} catch (Throwable ex) {
|
||||
@ -144,6 +158,20 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||
protected abstract PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body)
|
||||
throws Throwable;
|
||||
|
||||
@Override
|
||||
public final PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo) {
|
||||
try {
|
||||
return doGetRefund(outTradeNo, outRefundNo);
|
||||
} catch (Throwable ex) {
|
||||
log.error("[getRefund][客户端({}) outTradeNo({}) outRefundNo({}) 查询退款单异常]",
|
||||
getId(), outTradeNo, outRefundNo, ex);
|
||||
throw buildPayException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo)
|
||||
throws Throwable;
|
||||
|
||||
// ========== 各种工具方法 ==========
|
||||
|
||||
private PayException buildPayException(Throwable ex) {
|
||||
|
@ -17,15 +17,22 @@ import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayConfig;
|
||||
import com.alipay.api.AlipayResponse;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
|
||||
import com.alipay.api.domain.AlipayTradeQueryModel;
|
||||
import com.alipay.api.domain.AlipayTradeRefundModel;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
|
||||
import com.alipay.api.request.AlipayTradeQueryRequest;
|
||||
import com.alipay.api.request.AlipayTradeRefundRequest;
|
||||
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
|
||||
import com.alipay.api.response.AlipayTradeQueryResponse;
|
||||
import com.alipay.api.response.AlipayTradeRefundResponse;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
@ -63,7 +70,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
||||
*/
|
||||
protected PayOrderRespDTO buildClosedPayOrderRespDTO(PayOrderUnifiedReqDTO reqDTO, AlipayResponse response) {
|
||||
Assert.isFalse(response.isSuccess());
|
||||
return PayOrderRespDTO.build(response.getSubCode(), response.getSubMsg(),
|
||||
return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
|
||||
reqDTO.getOutTradeNo(), response);
|
||||
}
|
||||
|
||||
@ -76,10 +83,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
||||
|
||||
// 2. 解析订单的状态
|
||||
// 额外说明:支付宝不仅仅支付成功会回调,再各种触发支付单数据变化时,都会进行回调,所以这里 status 的解析会写的比较复杂
|
||||
String tradeStatus = bodyObj.get("trade_status");
|
||||
Integer status = Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus()
|
||||
: ObjectUtils.equalsAny(tradeStatus, "TRADE_FINISHED", "TRADE_SUCCESS") ? PayOrderStatusRespEnum.SUCCESS.getStatus()
|
||||
: Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null;
|
||||
Integer status = parseStatus(bodyObj.get("trade_status"));
|
||||
// 特殊逻辑: 支付宝没有退款成功的状态,所以,如果有退款金额,我们认为是退款成功
|
||||
if (MapUtil.getDouble(bodyObj, "refund_fee", 0D) > 0) {
|
||||
status = PayOrderStatusRespEnum.REFUND.getStatus();
|
||||
@ -87,10 +91,40 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
||||
Assert.notNull(status, (Supplier<Throwable>) () -> {
|
||||
throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", body));
|
||||
});
|
||||
return new PayOrderRespDTO(status, bodyObj.get("trade_no"), bodyObj.get("seller_id"), parseTime(params.get("gmt_payment")),
|
||||
return PayOrderRespDTO.of(status, bodyObj.get("trade_no"), bodyObj.get("seller_id"), parseTime(params.get("gmt_payment")),
|
||||
bodyObj.get("out_trade_no"), body);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doGetOrder(String outTradeNo) throws Throwable {
|
||||
// 1.1 构建 AlipayTradeRefundModel 请求
|
||||
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
|
||||
model.setOutTradeNo(outTradeNo);
|
||||
// 1.2 构建 AlipayTradeQueryRequest 请求
|
||||
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
|
||||
request.setBizModel(model);
|
||||
|
||||
// 2.1 执行请求
|
||||
AlipayTradeQueryResponse response = client.execute(request);
|
||||
if (!response.isSuccess()) { // 不成功,例如说订单不存在
|
||||
return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
|
||||
outTradeNo, response);
|
||||
}
|
||||
// 2.2 解析订单的状态
|
||||
Integer status = parseStatus(response.getTradeStatus());
|
||||
Assert.notNull(status, (Supplier<Throwable>) () -> {
|
||||
throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody()));
|
||||
});
|
||||
return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()),
|
||||
outTradeNo, response);
|
||||
}
|
||||
|
||||
private static Integer parseStatus(String tradeStatus) {
|
||||
return Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus()
|
||||
: ObjectUtils.equalsAny(tradeStatus, "TRADE_FINISHED", "TRADE_SUCCESS") ? PayOrderStatusRespEnum.SUCCESS.getStatus()
|
||||
: Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null;
|
||||
}
|
||||
|
||||
// ============ 退款相关 ==========
|
||||
|
||||
/**
|
||||
@ -112,16 +146,15 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
||||
request.setBizModel(model);
|
||||
|
||||
// 2.1 执行请求
|
||||
AlipayTradeRefundResponse response = client.execute(request);
|
||||
AlipayTradeRefundResponse response = client.execute(request);
|
||||
if (!response.isSuccess()) {
|
||||
return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
|
||||
}
|
||||
// 2.2 创建返回结果
|
||||
// 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。
|
||||
// 另外,支付宝没有退款单号,所以不用设置
|
||||
if (response.isSuccess()) {
|
||||
return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
|
||||
reqDTO.getOutRefundNo(), response);
|
||||
} else {
|
||||
return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
|
||||
}
|
||||
return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
|
||||
reqDTO.getOutRefundNo(), response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,6 +167,35 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
||||
throw new UnsupportedOperationException("支付宝无退款回调");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws AlipayApiException {
|
||||
// 1.1 构建 AlipayTradeFastpayRefundQueryModel 请求
|
||||
AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
|
||||
model.setOutTradeNo(outTradeNo);
|
||||
model.setOutRequestNo(outRefundNo);
|
||||
model.setQueryOptions(Collections.singletonList("gmt_refund_pay"));
|
||||
// 1.2 构建 AlipayTradeFastpayRefundQueryRequest 请求
|
||||
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
|
||||
request.setBizModel(model);
|
||||
|
||||
// 2.1 执行请求
|
||||
AlipayTradeFastpayRefundQueryResponse response = client.execute(request);
|
||||
if (!response.isSuccess()) {
|
||||
// 明确不存在的情况,应该就是失败,可进行关闭
|
||||
if (ObjectUtils.equalsAny(response.getSubCode(), "TRADE_NOT_EXIST", "ACQ.TRADE_NOT_EXIST")) {
|
||||
return PayRefundRespDTO.failureOf(outRefundNo, response);
|
||||
}
|
||||
// 可能存在“ACQ.SYSTEM_ERROR”系统错误等情况,所以返回 WAIT 继续等待
|
||||
return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
|
||||
}
|
||||
// 2.2 创建返回结果
|
||||
if (Objects.equals(response.getRefundStatus(), "REFUND_SUCCESS")) {
|
||||
return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
|
||||
outRefundNo, response);
|
||||
}
|
||||
return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
|
||||
}
|
||||
|
||||
// ========== 各种工具方法 ==========
|
||||
|
||||
protected String formatAmount(Integer amount) {
|
||||
|
@ -2,10 +2,12 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.date.TemporalAccessorUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
@ -16,10 +18,8 @@ import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
@ -90,7 +90,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
} catch (WxPayException e) {
|
||||
String errorCode = getErrorCode(e);
|
||||
String errorMessage = getErrorMessage(e);
|
||||
return PayOrderRespDTO.build(errorCode, errorMessage,
|
||||
return PayOrderRespDTO.closedOf(errorCode, errorMessage,
|
||||
reqDTO.getOutTradeNo(), e.getXmlString());
|
||||
}
|
||||
}
|
||||
@ -115,7 +115,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
|
||||
@Override
|
||||
public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws WxPayException {
|
||||
// 微信支付 v2 回调结果处理
|
||||
switch (config.getApiVersion()) {
|
||||
case API_VERSION_V2:
|
||||
return doParseOrderNotifyV2(body);
|
||||
@ -130,10 +129,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
// 1. 解析回调
|
||||
WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body);
|
||||
// 2. 构建结果
|
||||
// 微信支付的回调,只有 SUCCESS 支付成功、CLOSED 支付失败两种情况,无需像支付宝一样解析的比较复杂
|
||||
// V2 微信支付的回调,只有 SUCCESS 支付成功、CLOSED 支付失败两种情况,无需像支付宝一样解析的比较复杂
|
||||
Integer status = Objects.equals(response.getResultCode(), "SUCCESS") ?
|
||||
PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus();
|
||||
return new PayOrderRespDTO(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
|
||||
return PayOrderRespDTO.of(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
|
||||
response.getOutTradeNo(), body);
|
||||
}
|
||||
|
||||
@ -142,14 +141,79 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null);
|
||||
WxPayOrderNotifyV3Result.DecryptNotifyResult result = response.getResult();
|
||||
// 2. 构建结果
|
||||
// 微信支付的回调,只有 SUCCESS 支付成功、CLOSED 支付失败两种情况,无需像支付宝一样解析的比较复杂
|
||||
Integer status = Objects.equals(result.getTradeState(), "SUCCESS") ?
|
||||
PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus();
|
||||
Integer status = parseStatus(result.getTradeState());
|
||||
String openid = result.getPayer() != null ? result.getPayer().getOpenid() : null;
|
||||
return new PayOrderRespDTO(status, result.getTransactionId(), openid, parseDateV3(result.getSuccessTime()),
|
||||
return PayOrderRespDTO.of(status, result.getTransactionId(), openid, parseDateV3(result.getSuccessTime()),
|
||||
result.getOutTradeNo(), body);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doGetOrder(String outTradeNo) throws Throwable {
|
||||
try {
|
||||
switch (config.getApiVersion()) {
|
||||
case API_VERSION_V2:
|
||||
return doGetOrderV2(outTradeNo);
|
||||
case WxPayClientConfig.API_VERSION_V3:
|
||||
return doGetOrderV3(outTradeNo);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
|
||||
}
|
||||
} catch (WxPayException e) {
|
||||
if (ObjectUtils.equalsAny(e.getErrCode(), "ORDERNOTEXIST", "ORDER_NOT_EXIST")) {
|
||||
String errorCode = getErrorCode(e);
|
||||
String errorMessage = getErrorMessage(e);
|
||||
return PayOrderRespDTO.closedOf(errorCode, errorMessage,
|
||||
outTradeNo, e.getXmlString());
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private PayOrderRespDTO doGetOrderV2(String outTradeNo) throws WxPayException {
|
||||
// 构建 WxPayUnifiedOrderRequest 对象
|
||||
WxPayOrderQueryRequest request = WxPayOrderQueryRequest.newBuilder()
|
||||
.outTradeNo(outTradeNo).build();
|
||||
// 执行请求
|
||||
WxPayOrderQueryResult response = client.queryOrder(request);
|
||||
|
||||
// 转换结果
|
||||
Integer status = parseStatus(response.getTradeState());
|
||||
return PayOrderRespDTO.of(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
|
||||
outTradeNo, response);
|
||||
}
|
||||
|
||||
private PayOrderRespDTO doGetOrderV3(String outTradeNo) throws WxPayException {
|
||||
// 构建 WxPayUnifiedOrderRequest 对象
|
||||
WxPayOrderQueryV3Request request = new WxPayOrderQueryV3Request()
|
||||
.setOutTradeNo(outTradeNo);
|
||||
// 执行请求
|
||||
WxPayOrderQueryV3Result response = client.queryOrderV3(request);
|
||||
|
||||
// 转换结果
|
||||
Integer status = parseStatus(response.getTradeState());
|
||||
String openid = response.getPayer() != null ? response.getPayer().getOpenid() : null;
|
||||
return PayOrderRespDTO.of(status, response.getTransactionId(), openid, parseDateV3(response.getSuccessTime()),
|
||||
outTradeNo, response);
|
||||
}
|
||||
|
||||
private static Integer parseStatus(String tradeState) {
|
||||
switch (tradeState) {
|
||||
case "NOTPAY":
|
||||
case "USERPAYING": // 支付中,等待用户输入密码(条码支付独有)
|
||||
return PayOrderStatusRespEnum.WAITING.getStatus();
|
||||
case "SUCCESS":
|
||||
return PayOrderStatusRespEnum.SUCCESS.getStatus();
|
||||
case "REFUND":
|
||||
return PayOrderStatusRespEnum.REFUND.getStatus();
|
||||
case "CLOSED":
|
||||
case "REVOKED": // 已撤销(刷卡支付独有)
|
||||
case "PAYERROR": // 支付失败(其它原因,如银行返回失败)
|
||||
return PayOrderStatusRespEnum.CLOSED.getStatus();
|
||||
default:
|
||||
throw new IllegalArgumentException(StrUtil.format("未知的支付状态({})", tradeState));
|
||||
}
|
||||
}
|
||||
|
||||
// ============ 退款相关 ==========
|
||||
|
||||
@Override
|
||||
@ -183,7 +247,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
// 2.1 执行请求
|
||||
WxPayRefundResult response = client.refundV2(request);
|
||||
// 2.2 创建返回结果
|
||||
if (Objects.equals("SUCCESS", response.getResultCode())) {
|
||||
if (Objects.equals("SUCCESS", response.getResultCode())) { // V2 情况下,不直接返回退款成功,而是等待异步通知
|
||||
return PayRefundRespDTO.waitingOf(response.getRefundId(),
|
||||
reqDTO.getOutRefundNo(), response);
|
||||
}
|
||||
@ -249,6 +313,83 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws WxPayException {
|
||||
try {
|
||||
switch (config.getApiVersion()) {
|
||||
case API_VERSION_V2:
|
||||
return doGetRefundV2(outTradeNo, outRefundNo);
|
||||
case WxPayClientConfig.API_VERSION_V3:
|
||||
return doGetRefundV3(outTradeNo, outRefundNo);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
|
||||
}
|
||||
} catch (WxPayException e) {
|
||||
if (ObjectUtils.equalsAny(e.getErrCode(), "REFUNDNOTEXIST", "RESOURCE_NOT_EXISTS")) {
|
||||
String errorCode = getErrorCode(e);
|
||||
String errorMessage = getErrorMessage(e);
|
||||
return PayRefundRespDTO.failureOf(errorCode, errorMessage,
|
||||
outRefundNo, e.getXmlString());
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private PayRefundRespDTO doGetRefundV2(String outTradeNo, String outRefundNo) throws WxPayException {
|
||||
// 1. 构建 WxPayRefundRequest 请求
|
||||
WxPayRefundQueryRequest request = WxPayRefundQueryRequest.newBuilder()
|
||||
.outTradeNo(outTradeNo)
|
||||
.outRefundNo(outRefundNo)
|
||||
.build();
|
||||
// 2.1 执行请求
|
||||
WxPayRefundQueryResult response = client.refundQuery(request);
|
||||
// 2.2 创建返回结果
|
||||
if (!Objects.equals("SUCCESS", response.getResultCode())) {
|
||||
return PayRefundRespDTO.waitingOf(null,
|
||||
outRefundNo, response);
|
||||
}
|
||||
WxPayRefundQueryResult.RefundRecord refund = CollUtil.findOne(response.getRefundRecords(),
|
||||
record -> record.getOutRefundNo().equals(outRefundNo));
|
||||
if (refund == null) {
|
||||
return PayRefundRespDTO.failureOf(outRefundNo, response);
|
||||
}
|
||||
switch (refund.getRefundStatus()) {
|
||||
case "SUCCESS":
|
||||
return PayRefundRespDTO.successOf(refund.getRefundId(), parseDateV2B(refund.getRefundSuccessTime()),
|
||||
outRefundNo, response);
|
||||
case "PROCESSING":
|
||||
return PayRefundRespDTO.waitingOf(refund.getRefundId(),
|
||||
outRefundNo, response);
|
||||
case "CHANGE": // 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者财付通转账的方式进行退款
|
||||
case "FAIL":
|
||||
return PayRefundRespDTO.failureOf(outRefundNo, response);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("未知的退款状态(%s)", refund.getRefundStatus()));
|
||||
}
|
||||
}
|
||||
|
||||
private PayRefundRespDTO doGetRefundV3(String outTradeNo, String outRefundNo) throws WxPayException {
|
||||
// 1. 构建 WxPayRefundRequest 请求
|
||||
WxPayRefundQueryV3Request request = new WxPayRefundQueryV3Request();
|
||||
request.setOutRefundNo(outRefundNo);
|
||||
// 2.1 执行请求
|
||||
WxPayRefundQueryV3Result response = client.refundQueryV3(request);
|
||||
// 2.2 创建返回结果
|
||||
switch (response.getStatus()) {
|
||||
case "SUCCESS":
|
||||
return PayRefundRespDTO.successOf(response.getRefundId(), parseDateV3(response.getSuccessTime()),
|
||||
outRefundNo, response);
|
||||
case "PROCESSING":
|
||||
return PayRefundRespDTO.waitingOf(response.getRefundId(),
|
||||
outRefundNo, response);
|
||||
case "ABNORMAL": // 退款异常
|
||||
case "CLOSED":
|
||||
return PayRefundRespDTO.failureOf(outRefundNo, response);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("未知的退款状态(%s)", response.getStatus()));
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 各种工具方法 ==========
|
||||
|
||||
static String formatDateV2(LocalDateTime time) {
|
||||
|
@ -68,7 +68,7 @@ public class WxBarPayClient extends AbstractWxPayClient {
|
||||
try {
|
||||
WxPayMicropayResult response = client.micropay(request);
|
||||
// 支付成功,例如说:1)用户输入了密码;2)用户免密支付
|
||||
return new PayOrderRespDTO(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
|
||||
return PayOrderRespDTO.successOf(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
|
||||
response.getOutTradeNo(), response)
|
||||
.setDisplayMode(PayOrderDisplayModeEnum.BAR_CODE.getMode());
|
||||
} catch (WxPayException ex) {
|
||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
||||
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
|
||||
|
@ -33,6 +33,16 @@ public enum PayOrderStatusRespEnum {
|
||||
return Objects.equals(status, SUCCESS.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否已退款
|
||||
*
|
||||
* @param status 状态
|
||||
* @return 是否支付成功
|
||||
*/
|
||||
public static boolean isRefund(Integer status) {
|
||||
return Objects.equals(status, REFUND.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否支付关闭
|
||||
*
|
||||
|
@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
@ -41,7 +40,6 @@ public class BaseDbAndRedisUnitTest {
|
||||
|
||||
// Redis 配置类
|
||||
RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
|
||||
RedisAutoConfiguration.class, // Spring Redis 自动配置类
|
||||
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
|
||||
RedissonAutoConfiguration.class, // Redisson 自动高配置类
|
||||
})
|
||||
|
@ -39,7 +39,7 @@ public class MemberAddressDO extends BaseDO {
|
||||
/**
|
||||
* 地区编号
|
||||
*/
|
||||
private Integer areaId;
|
||||
private Long areaId;
|
||||
/**
|
||||
* 收件详细地址
|
||||
*/
|
||||
|
@ -23,9 +23,8 @@ CREATE TABLE IF NOT EXISTS "member_address" (
|
||||
"name" varchar(10) NOT NULL,
|
||||
"mobile" varchar(20) NOT NULL,
|
||||
"area_id" bigint(20) NOT NULL,
|
||||
"post_code" varchar(16) NOT NULL,
|
||||
"detail_address" varchar(250) NOT NULL,
|
||||
"defaulted" bit NOT NULL,
|
||||
"default_status" bit NOT NULL,
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
@ -23,7 +23,7 @@ public interface ErrorCodeConstants {
|
||||
// ========== ORDER 模块 1007002000 ==========
|
||||
ErrorCode ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在");
|
||||
ErrorCode ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付");
|
||||
ErrorCode ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付");
|
||||
ErrorCode ORDER_STATUS_IS_SUCCESS = new ErrorCode(1007002002, "订单已支付,请刷新页面");
|
||||
ErrorCode ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期");
|
||||
ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}");
|
||||
ErrorCode ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款");
|
||||
@ -31,6 +31,7 @@ public interface ErrorCodeConstants {
|
||||
// ========== ORDER 模块(拓展单) 1007003000 ==========
|
||||
ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在");
|
||||
ErrorCode ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付");
|
||||
ErrorCode ORDER_EXTENSION_IS_PAID = new ErrorCode(1007003002, "订单已支付,请等待支付结果");
|
||||
|
||||
// ========== 支付模块(退款) 1007006000 ==========
|
||||
ErrorCode REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额");
|
||||
|
@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@ -44,8 +43,6 @@ public class PayRefundController {
|
||||
private PayRefundService refundService;
|
||||
@Resource
|
||||
private PayAppService appService;
|
||||
@Resource
|
||||
private PayOrderService orderService;
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得退款订单")
|
||||
|
@ -70,6 +70,12 @@ public class PayRefundDO extends BaseDO {
|
||||
* 关联 {@link PayOrderDO#getId()}
|
||||
*/
|
||||
private Long orderId;
|
||||
/**
|
||||
* 支付订单编号
|
||||
*
|
||||
* 冗余 {@link PayOrderDO#getNo()}
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
// ========== 商户相关字段 ==========
|
||||
/**
|
||||
|
@ -5,6 +5,9 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface PayOrderExtensionMapper extends BaseMapperX<PayOrderExtensionDO> {
|
||||
|
||||
@ -17,4 +20,14 @@ public interface PayOrderExtensionMapper extends BaseMapperX<PayOrderExtensionDO
|
||||
.eq(PayOrderExtensionDO::getId, id).eq(PayOrderExtensionDO::getStatus, status));
|
||||
}
|
||||
|
||||
default List<PayOrderExtensionDO> selectListByOrderId(Long orderId) {
|
||||
return selectList(PayOrderExtensionDO::getOrderId, orderId);
|
||||
}
|
||||
|
||||
default List<PayOrderExtensionDO> selectListByStatusAndCreateTimeGe(Integer status, LocalDateTime minCreateTime) {
|
||||
return selectList(new LambdaQueryWrapper<PayOrderExtensionDO>()
|
||||
.eq(PayOrderExtensionDO::getStatus, status)
|
||||
.ge(PayOrderExtensionDO::getCreateTime, minCreateTime));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
@ -52,4 +53,10 @@ public interface PayOrderMapper extends BaseMapperX<PayOrderDO> {
|
||||
.eq(PayOrderDO::getId, id).eq(PayOrderDO::getStatus, status));
|
||||
}
|
||||
|
||||
default List<PayOrderDO> selectListByStatusAndExpireTimeLt(Integer status, LocalDateTime expireTime) {
|
||||
return selectList(new LambdaQueryWrapper<PayOrderDO>()
|
||||
.eq(PayOrderDO::getStatus, status)
|
||||
.lt(PayOrderDO::getExpireTime, expireTime));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -68,4 +68,8 @@ public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
|
||||
.orderByDesc(PayRefundDO::getId));
|
||||
}
|
||||
|
||||
default List<PayRefundDO> selectListByStatus(Integer status) {
|
||||
return selectList(PayRefundDO::getStatus, status);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.pay.job.order;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 支付订单的过期 Job
|
||||
*
|
||||
* 支付超过过期时间时,支付渠道是不会通知进行过期,所以需要定时进行过期关闭。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@TenantJob
|
||||
public class PayOrderExpireJob implements JobHandler {
|
||||
|
||||
@Resource
|
||||
private PayOrderService orderService;
|
||||
|
||||
@Override
|
||||
public String execute(String param) {
|
||||
int count = orderService.expireOrder();
|
||||
return StrUtil.format("支付过期 {} 个", count);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.pay.job.order;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 支付订单的同步 Job
|
||||
*
|
||||
* 由于支付订单的状态,是由支付渠道异步通知进行同步,考虑到异步通知可能会失败(小概率),所以需要定时进行同步。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@TenantJob
|
||||
public class PayOrderSyncJob implements JobHandler {
|
||||
|
||||
/**
|
||||
* 同步创建时间在 N 分钟之前的订单
|
||||
*
|
||||
* 为什么同步 10 分钟之前的订单?
|
||||
* 因为一个订单发起支付,到支付成功,大多数在 10 分钟内,需要保证轮询到。
|
||||
* 如果设置为 30、60 或者更大时间范围,会导致轮询的订单太多,影响性能。当然,你也可以根据自己的业务情况来处理。
|
||||
*/
|
||||
private static final Duration CREATE_TIME_DURATION_BEFORE = Duration.ofMinutes(10);
|
||||
|
||||
@Resource
|
||||
private PayOrderService orderService;
|
||||
|
||||
@Override
|
||||
public String execute(String param) {
|
||||
LocalDateTime minCreateTime = LocalDateTime.now().minus(CREATE_TIME_DURATION_BEFORE);
|
||||
int count = orderService.syncOrder(minCreateTime);
|
||||
return StrUtil.format("同步支付订单 {} 个", count);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* 占位,无特殊含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.pay.job;
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.pay.job.refund;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 退款订单的同步 Job
|
||||
*
|
||||
* 由于退款订单的状态,是由支付渠道异步通知进行同步,考虑到异步通知可能会失败(小概率),所以需要定时进行同步。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@TenantJob
|
||||
public class PayRefundSyncJob implements JobHandler {
|
||||
|
||||
@Resource
|
||||
private PayRefundService refundService;
|
||||
|
||||
@Override
|
||||
public String execute(String param) {
|
||||
int count = refundService.syncRefund();
|
||||
return StrUtil.format("同步退款订单 {} 个", count);
|
||||
}
|
||||
|
||||
}
|
@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -105,4 +106,19 @@ public interface PayOrderService {
|
||||
*/
|
||||
PayOrderExtensionDO getOrderExtension(Long id);
|
||||
|
||||
/**
|
||||
* 同步订单的支付状态
|
||||
*
|
||||
* @param minCreateTime 最小创建时间
|
||||
* @return 同步到已支付的订单数量
|
||||
*/
|
||||
int syncOrder(LocalDateTime minCreateTime);
|
||||
|
||||
/**
|
||||
* 将已过期的订单,状态修改为已关闭
|
||||
*
|
||||
* @return 过期的订单数量
|
||||
*/
|
||||
int expireOrder();
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.module.pay.service.order;
|
||||
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
@ -33,12 +33,14 @@ import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.util.MoneyUtils;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -129,10 +131,10 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
|
||||
@Override // 注意,这里不能添加事务注解,避免调用支付渠道失败时,将 PayOrderExtensionDO 回滚了
|
||||
public PayOrderSubmitRespVO submitOrder(PayOrderSubmitReqVO reqVO, String userIp) {
|
||||
// 1. 获得 PayOrderDO ,并校验其是否存在
|
||||
// 1.1 获得 PayOrderDO ,并校验其是否存在
|
||||
PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
|
||||
// 1.2 校验支付渠道是否有效
|
||||
PayChannelDO channel = validatePayChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
|
||||
// 1.32 校验支付渠道是否有效
|
||||
PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
|
||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||
|
||||
// 2. 插入 PayOrderExtensionDO
|
||||
@ -173,16 +175,52 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
if (order == null) { // 是否存在
|
||||
throw exception(ORDER_NOT_FOUND);
|
||||
}
|
||||
if (PayOrderStatusEnum.isSuccess(order.getStatus())) { // 校验状态,发现已支付
|
||||
throw exception(ORDER_STATUS_IS_SUCCESS);
|
||||
}
|
||||
if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
|
||||
throw exception(ORDER_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期
|
||||
throw exception(ORDER_IS_EXPIRED);
|
||||
}
|
||||
|
||||
// 【重要】校验是否支付拓展单已支付,只是没有回调、或者数据不正常
|
||||
validateOrderActuallyPaid(id);
|
||||
return order;
|
||||
}
|
||||
|
||||
private PayChannelDO validatePayChannelCanSubmit(Long appId, String channelCode) {
|
||||
/**
|
||||
* 校验支付订单实际已支付
|
||||
*
|
||||
* @param id 支付编号
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void validateOrderActuallyPaid(Long id) {
|
||||
List<PayOrderExtensionDO> orderExtensions = orderExtensionMapper.selectListByOrderId(id);
|
||||
orderExtensions.forEach(orderExtension -> {
|
||||
// 情况一:校验数据库中的 orderExtension 是不是已支付
|
||||
if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) {
|
||||
log.warn("[validateOrderCanSubmit][order({}) 的 extension({}) 已支付,可能是数据不一致]",
|
||||
id, orderExtension.getId());
|
||||
throw exception(ORDER_EXTENSION_IS_PAID);
|
||||
}
|
||||
// 情况二:调用三方接口,查询支付单状态,是不是已支付
|
||||
PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId());
|
||||
if (payClient == null) {
|
||||
log.error("[validateOrderCanSubmit][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
|
||||
return;
|
||||
}
|
||||
PayOrderRespDTO respDTO = payClient.getOrder(orderExtension.getNo());
|
||||
if (respDTO != null && PayOrderStatusRespEnum.isSuccess(respDTO.getStatus())) {
|
||||
log.warn("[validateOrderCanSubmit][order({}) 的 PayOrderRespDTO({}) 已支付,可能是回调延迟]",
|
||||
id, toJsonString(respDTO));
|
||||
throw exception(ORDER_EXTENSION_IS_PAID);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private PayChannelDO validateChannelCanSubmit(Long appId, String channelCode) {
|
||||
// 校验 App
|
||||
appService.validPayApp(appId);
|
||||
// 校验支付渠道是否有效
|
||||
@ -261,7 +299,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
throw exception(ORDER_EXTENSION_NOT_FOUND);
|
||||
}
|
||||
if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
|
||||
log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新]", orderExtension.getId());
|
||||
log.info("[updateOrderExtensionSuccess][orderExtension({}) 已经是已支付,无需更新]", orderExtension.getId());
|
||||
return orderExtension;
|
||||
}
|
||||
if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付
|
||||
@ -274,7 +312,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[updateOrderExtensionSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId());
|
||||
log.info("[updateOrderExtensionSuccess][orderExtension({}) 更新为已支付]", orderExtension.getId());
|
||||
return orderExtension;
|
||||
}
|
||||
|
||||
@ -295,7 +333,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
}
|
||||
if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新
|
||||
&& Objects.equals(order.getExtensionId(), orderExtension.getId())) {
|
||||
log.info("[updateOrderExtensionSuccess][支付订单({}) 已经是已支付,无需更新]", order.getId());
|
||||
log.info("[updateOrderExtensionSuccess][order({}) 已经是已支付,无需更新]", order.getId());
|
||||
return true;
|
||||
}
|
||||
if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
|
||||
@ -313,7 +351,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
throw exception(ORDER_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[updateOrderExtensionSuccess][支付订单({}) 更新为已支付]", order.getId());
|
||||
log.info("[updateOrderExtensionSuccess][order({}) 更新为已支付]", order.getId());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -328,12 +366,12 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
throw exception(ORDER_EXTENSION_NOT_FOUND);
|
||||
}
|
||||
if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { // 如果已经是关闭,直接返回,不用重复更新
|
||||
log.info("[updateOrderExtensionClosed][支付拓展单({}) 已经是支付关闭,无需更新]", orderExtension.getId());
|
||||
log.info("[updateOrderExtensionClosed][orderExtension({}) 已经是支付关闭,无需更新]", orderExtension.getId());
|
||||
return;
|
||||
}
|
||||
// 一般出现先是支付成功,然后支付关闭,都是全部退款导致关闭的场景。这个情况,我们不更新支付拓展单,只通过退款流程,更新支付单
|
||||
if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) {
|
||||
log.info("[updateOrderExtensionClosed][支付拓展单({}) 是已支付,无需更新为支付关闭]", orderExtension.getId());
|
||||
log.info("[updateOrderExtensionClosed][orderExtension({}) 是已支付,无需更新为支付关闭]", orderExtension.getId());
|
||||
return;
|
||||
}
|
||||
if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付
|
||||
@ -347,7 +385,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[updateOrderExtensionClosed][支付拓展单({}) 更新为支付关闭]", orderExtension.getId());
|
||||
log.info("[updateOrderExtensionClosed][orderExtension({}) 更新为支付关闭]", orderExtension.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -378,6 +416,128 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
return orderExtensionMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int syncOrder(LocalDateTime minCreateTime) {
|
||||
// 1. 查询指定创建时间内的待支付订单
|
||||
List<PayOrderExtensionDO> orderExtensions = orderExtensionMapper.selectListByStatusAndCreateTimeGe(
|
||||
PayOrderStatusEnum.WAITING.getStatus(), minCreateTime);
|
||||
if (CollUtil.isEmpty(orderExtensions)) {
|
||||
return 0;
|
||||
}
|
||||
// 2. 遍历执行
|
||||
int count = 0;
|
||||
for (PayOrderExtensionDO orderExtension : orderExtensions) {
|
||||
count += syncOrder(orderExtension) ? 1 : 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步单个支付拓展单
|
||||
*
|
||||
* @param orderExtension 支付拓展单
|
||||
* @return 是否已支付
|
||||
*/
|
||||
private boolean syncOrder(PayOrderExtensionDO orderExtension) {
|
||||
try {
|
||||
// 1.1 查询支付订单信息
|
||||
PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId());
|
||||
if (payClient == null) {
|
||||
log.error("[syncOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
|
||||
return false;
|
||||
}
|
||||
PayOrderRespDTO respDTO = payClient.getOrder(orderExtension.getNo());
|
||||
// 1.2 回调支付结果
|
||||
notifyOrder(orderExtension.getChannelId(), respDTO);
|
||||
|
||||
// 2. 如果是已支付,则返回 true
|
||||
return PayOrderStatusRespEnum.isSuccess(respDTO.getStatus());
|
||||
} catch (Throwable e) {
|
||||
log.error("[syncOrder][orderExtension({}) 同步支付状态异常]", orderExtension.getId(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expireOrder() {
|
||||
// 1. 查询过期的待支付订单
|
||||
List<PayOrderDO> orders = orderMapper.selectListByStatusAndExpireTimeLt(
|
||||
PayOrderStatusEnum.WAITING.getStatus(), LocalDateTime.now());
|
||||
if (CollUtil.isEmpty(orders)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. 遍历执行
|
||||
int count = 0;
|
||||
for (PayOrderDO order : orders) {
|
||||
count += expireOrder(order) ? 1 : 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步单个支付单
|
||||
*
|
||||
* @param order 支付单
|
||||
* @return 是否已过期
|
||||
*/
|
||||
private boolean expireOrder(PayOrderDO order) {
|
||||
try {
|
||||
// 1. 需要先处理关联的支付拓展单,避免错误的过期已支付 or 已退款的订单
|
||||
List<PayOrderExtensionDO> orderExtensions = orderExtensionMapper.selectListByOrderId(order.getId());
|
||||
for (PayOrderExtensionDO orderExtension : orderExtensions) {
|
||||
if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) {
|
||||
continue;
|
||||
}
|
||||
// 情况一:校验数据库中的 orderExtension 是不是已支付
|
||||
if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) {
|
||||
log.error("[expireOrder][order({}) 的 extension({}) 已支付,可能是数据不一致]",
|
||||
order.getId(), orderExtension.getId());
|
||||
return false;
|
||||
}
|
||||
// 情况二:调用三方接口,查询支付单状态,是不是已支付/已退款
|
||||
PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId());
|
||||
if (payClient == null) {
|
||||
log.error("[expireOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
|
||||
return false;
|
||||
}
|
||||
PayOrderRespDTO respDTO = payClient.getOrder(orderExtension.getNo());
|
||||
if (PayOrderStatusRespEnum.isRefund(respDTO.getStatus())) {
|
||||
// 补充说明:按道理,应该是 WAITING => SUCCESS => REFUND 状态,如果直接 WAITING => REFUND 状态,说明中间丢了过程
|
||||
// 此时,需要人工介入,手工补齐数据,保持 WAITING => SUCCESS => REFUND 的过程
|
||||
log.error("[expireOrder][extension({}) 的 PayOrderRespDTO({}) 已退款,可能是回调延迟]",
|
||||
orderExtension.getId(), toJsonString(respDTO));
|
||||
return false;
|
||||
}
|
||||
if (PayOrderStatusRespEnum.isSuccess(respDTO.getStatus())) {
|
||||
notifyOrder(orderExtension.getChannelId(), respDTO);
|
||||
return false;
|
||||
}
|
||||
// 兜底逻辑:将支付拓展单更新为已关闭
|
||||
PayOrderExtensionDO updateObj = new PayOrderExtensionDO().setStatus(PayOrderStatusEnum.CLOSED.getStatus())
|
||||
.setChannelNotifyData(toJsonString(respDTO));
|
||||
if (orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), PayOrderStatusEnum.WAITING.getStatus(),
|
||||
updateObj) == 0) {
|
||||
log.error("[expireOrder][extension({}) 更新为支付关闭失败]", orderExtension.getId());
|
||||
return false;
|
||||
}
|
||||
log.info("[expireOrder][extension({}) 更新为支付关闭成功]", orderExtension.getId());
|
||||
}
|
||||
|
||||
// 2. 都没有上述情况,可以安心更新为已关闭
|
||||
PayOrderDO updateObj = new PayOrderDO().setStatus(PayOrderStatusEnum.CLOSED.getStatus());
|
||||
if (orderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateObj) == 0) {
|
||||
log.error("[expireOrder][order({}) 更新为支付关闭失败]", order.getId());
|
||||
return false;
|
||||
}
|
||||
log.info("[expireOrder][order({}) 更新为支付关闭失败]", order.getId());
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
log.error("[expireOrder][order({}) 过期订单异常]", order.getId(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得自身的代理对象,解决 AOP 生效问题
|
||||
*
|
||||
|
@ -64,4 +64,11 @@ public interface PayRefundService {
|
||||
*/
|
||||
void notifyRefund(Long channelId, PayRefundRespDTO notify);
|
||||
|
||||
/**
|
||||
* 同步渠道退款的退款状态
|
||||
*
|
||||
* @return 同步到状态的退款数量,包括退款成功、退款失败
|
||||
*/
|
||||
int syncRefund();
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.module.pay.service.refund;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||
@ -16,10 +16,9 @@ import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
|
||||
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
|
||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
@ -35,12 +34,11 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_FOUND;
|
||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 退款订单 Service 实现类
|
||||
@ -60,6 +58,8 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
|
||||
@Resource
|
||||
private PayRefundMapper refundMapper;
|
||||
@Resource
|
||||
private PayNoRedisDAO noRedisDAO;
|
||||
|
||||
@Resource
|
||||
private PayOrderService orderService;
|
||||
@ -91,7 +91,6 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createPayRefund(PayRefundCreateReqDTO reqDTO) {
|
||||
// 1.1 校验 App
|
||||
PayAppDO app = appService.validPayApp(reqDTO.getAppId());
|
||||
@ -108,12 +107,13 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
PayRefundDO refund = refundMapper.selectByAppIdAndMerchantRefundId(
|
||||
app.getId(), reqDTO.getMerchantRefundId());
|
||||
if (refund != null) {
|
||||
throw exception(ErrorCodeConstants.REFUND_EXISTS);
|
||||
throw exception(REFUND_EXISTS);
|
||||
}
|
||||
|
||||
// 2.1 插入退款单
|
||||
String no = noRedisDAO.generate(payProperties.getRefundNoPrefix());
|
||||
refund = PayRefundConvert.INSTANCE.convert(reqDTO)
|
||||
.setNo(generateRefundNo()).setOrderId(order.getId())
|
||||
.setNo(no).setOrderId(order.getId()).setOrderNo(order.getNo())
|
||||
.setChannelId(order.getChannelId()).setChannelCode(order.getChannelCode())
|
||||
// 商户相关的字段
|
||||
.setNotifyUrl(app.getRefundNotifyUrl())
|
||||
@ -123,20 +123,27 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
.setStatus(PayRefundStatusEnum.WAITING.getStatus())
|
||||
.setPayPrice(order.getPrice()).setRefundPrice(reqDTO.getPrice());
|
||||
refundMapper.insert(refund);
|
||||
// 2.2 向渠道发起退款申请
|
||||
PayOrderExtensionDO orderExtension = orderService.getOrderExtension(order.getExtensionId());
|
||||
PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO()
|
||||
.setPayPrice(order.getPrice())
|
||||
.setRefundPrice(reqDTO.getPrice())
|
||||
.setOutTradeNo(orderExtension.getNo())
|
||||
.setOutRefundNo(refund.getNo())
|
||||
.setNotifyUrl(genChannelRefundNotifyUrl(channel))
|
||||
.setReason(reqDTO.getReason());
|
||||
PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO);
|
||||
// 2.3 处理退款返回
|
||||
notifyRefund(channel, refundRespDTO);
|
||||
try {
|
||||
// 2.2 向渠道发起退款申请
|
||||
PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO()
|
||||
.setPayPrice(order.getPrice())
|
||||
.setRefundPrice(reqDTO.getPrice())
|
||||
.setOutTradeNo(order.getNo())
|
||||
.setOutRefundNo(refund.getNo())
|
||||
.setNotifyUrl(genChannelRefundNotifyUrl(channel))
|
||||
.setReason(reqDTO.getReason());
|
||||
PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO);
|
||||
// 2.3 处理退款返回
|
||||
getSelf().notifyRefund(channel, refundRespDTO);
|
||||
} catch (Throwable e) {
|
||||
// 注意:这里仅打印异常,不进行抛出。
|
||||
// 原因是:虽然调用支付渠道进行退款发生异常(网络请求超时),实际退款成功。这个结果,后续通过退款回调、或者退款轮询补偿可以拿到。
|
||||
// 最终,在异常的情况下,支付中心会异步回调业务的退款回调接口,提供退款结果
|
||||
log.error("[createPayRefund][退款 id({}) requestDTO({}) 发生异常]",
|
||||
refund.getId(), reqDTO, e);
|
||||
}
|
||||
|
||||
// 成功在 退款回调中处理
|
||||
// 返回退款编号
|
||||
return refund.getId();
|
||||
}
|
||||
|
||||
@ -149,21 +156,21 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
private PayOrderDO validatePayOrderCanRefund(PayRefundCreateReqDTO reqDTO) {
|
||||
PayOrderDO order = orderService.getOrder(reqDTO.getAppId(), reqDTO.getMerchantOrderId());
|
||||
if (order == null) {
|
||||
throw exception(ErrorCodeConstants.ORDER_NOT_FOUND);
|
||||
throw exception(ORDER_NOT_FOUND);
|
||||
}
|
||||
// 校验状态,必须是支付状态
|
||||
if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
|
||||
throw exception(ErrorCodeConstants.ORDER_STATUS_IS_NOT_SUCCESS);
|
||||
// 校验状态,必须是已支付、或者已退款
|
||||
if (!PayOrderStatusEnum.isSuccessOrRefund(order.getStatus())) {
|
||||
throw exception(ORDER_REFUND_FAIL_STATUS_ERROR);
|
||||
}
|
||||
|
||||
// 校验金额 退款金额不能大于原定的金额
|
||||
// 校验金额,退款金额不能大于原定的金额
|
||||
if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){
|
||||
throw exception(ErrorCodeConstants.REFUND_PRICE_EXCEED);
|
||||
throw exception(REFUND_PRICE_EXCEED);
|
||||
}
|
||||
// 是否有退款中的订单
|
||||
if (refundMapper.selectCountByAppIdAndOrderId(reqDTO.getAppId(), order.getId(),
|
||||
PayRefundStatusEnum.WAITING.getStatus()) > 0) {
|
||||
throw exception(ErrorCodeConstants.REFUND_HAS_REFUNDING);
|
||||
throw exception(REFUND_HAS_REFUNDING);
|
||||
}
|
||||
return order;
|
||||
}
|
||||
@ -178,38 +185,22 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
return payProperties.getRefundNotifyUrl() + "/" + channel.getId();
|
||||
}
|
||||
|
||||
private String generateRefundNo() {
|
||||
// wx
|
||||
// 2014
|
||||
// 10
|
||||
// 27
|
||||
// 20
|
||||
// 09
|
||||
// 39
|
||||
// 5522657
|
||||
// a690389285100
|
||||
// 目前的算法
|
||||
// 时间序列,年月日时分秒 14 位
|
||||
// 纯随机,6 位 TODO 芋艿:此处估计是会有问题的,后续在调整
|
||||
return DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + // 时间序列
|
||||
RandomUtil.randomInt(100000, 999999) // 随机。为什么是这个范围,因为偷懒
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyRefund(Long channelId, PayRefundRespDTO notify) {
|
||||
// 校验支付渠道是否有效
|
||||
channelService.validPayChannel(channelId);
|
||||
// 通知结果
|
||||
|
||||
// 校验支付渠道是否有效
|
||||
PayChannelDO channel = channelService.validPayChannel(channelId);
|
||||
// 更新退款订单
|
||||
TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify));
|
||||
TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyRefund(channel, notify));
|
||||
}
|
||||
|
||||
// TODO 芋艿:事务问题
|
||||
private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||
/**
|
||||
* 通知并更新订单的退款结果
|
||||
*
|
||||
* @param channel 支付渠道
|
||||
* @param notify 通知
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class) // 注意,如果是方法内调用该方法,需要通过 getSelf().notifyRefund(channel, notify) 调用,否则事务不生效
|
||||
public void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||
// 情况一:退款成功
|
||||
if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) {
|
||||
notifyRefundSuccess(channel, notify);
|
||||
@ -221,19 +212,19 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||
private void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||
// 1.1 查询 PayRefundDO
|
||||
PayRefundDO refund = refundMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutRefundNo());
|
||||
if (refund == null) {
|
||||
throw exception(ErrorCodeConstants.REFUND_NOT_FOUND);
|
||||
throw exception(REFUND_NOT_FOUND);
|
||||
}
|
||||
if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
|
||||
log.info("[notifyRefundSuccess][退款订单({}) 已经是退款成功,无需更新]", refund.getId());
|
||||
return;
|
||||
}
|
||||
if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) {
|
||||
throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
|
||||
throw exception(REFUND_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
// 1.2 更新 PayRefundDO
|
||||
PayRefundDO updateRefundObj = new PayRefundDO()
|
||||
@ -243,32 +234,31 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
.setChannelNotifyData(toJsonString(notify));
|
||||
int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj);
|
||||
if (updateCounts == 0) { // 校验状态,必须是等待状态
|
||||
throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
|
||||
throw exception(REFUND_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[notifyRefundSuccess][退款订单({}) 更新为退款成功]", refund.getId());
|
||||
|
||||
// 2. 更新订单
|
||||
orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice());
|
||||
|
||||
// 3. 插入退款通知记录 TODO 芋艿:退款成功
|
||||
// 3. 插入退款通知记录
|
||||
notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||
private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||
// 1.1 查询 PayRefundDO
|
||||
PayRefundDO refund = refundMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutRefundNo());
|
||||
if (refund == null) {
|
||||
throw exception(ErrorCodeConstants.REFUND_NOT_FOUND);
|
||||
throw exception(REFUND_NOT_FOUND);
|
||||
}
|
||||
if (PayRefundStatusEnum.isFailure(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
|
||||
log.info("[notifyRefundSuccess][退款订单({}) 已经是退款关闭,无需更新]", refund.getId());
|
||||
return;
|
||||
}
|
||||
if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) {
|
||||
throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
|
||||
throw exception(REFUND_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
// 1.2 更新 PayRefundDO
|
||||
PayRefundDO updateRefundObj = new PayRefundDO()
|
||||
@ -278,13 +268,64 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
.setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg());
|
||||
int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj);
|
||||
if (updateCounts == 0) { // 校验状态,必须是等待状态
|
||||
throw exception(ErrorCodeConstants.REFUND_STATUS_IS_NOT_WAITING);
|
||||
throw exception(REFUND_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId());
|
||||
|
||||
// 2. 插入退款通知记录 TODO 芋艿:退款失败
|
||||
// 2. 插入退款通知记录
|
||||
notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int syncRefund() {
|
||||
// 1. 查询指定创建时间内的待退款订单
|
||||
List<PayRefundDO> refunds = refundMapper.selectListByStatus(PayRefundStatusEnum.WAITING.getStatus());
|
||||
if (CollUtil.isEmpty(refunds)) {
|
||||
return 0;
|
||||
}
|
||||
// 2. 遍历执行
|
||||
int count = 0;
|
||||
for (PayRefundDO refund : refunds) {
|
||||
count += syncRefund(refund) ? 1 : 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步单个退款订单
|
||||
*
|
||||
* @param refund 退款订单
|
||||
* @return 是否同步到
|
||||
*/
|
||||
private boolean syncRefund(PayRefundDO refund) {
|
||||
try {
|
||||
// 1.1 查询退款订单信息
|
||||
PayClient payClient = payClientFactory.getPayClient(refund.getChannelId());
|
||||
if (payClient == null) {
|
||||
log.error("[syncRefund][渠道编号({}) 找不到对应的支付客户端]", refund.getChannelId());
|
||||
return false;
|
||||
}
|
||||
PayRefundRespDTO respDTO = payClient.getRefund(refund.getOrderNo(), refund.getNo());
|
||||
// 1.2 回调退款结果
|
||||
notifyRefund(refund.getChannelId(), respDTO);
|
||||
|
||||
// 2. 如果同步到,则返回 true
|
||||
return PayRefundStatusEnum.isSuccess(respDTO.getStatus())
|
||||
|| PayRefundStatusEnum.isFailure(respDTO.getStatus());
|
||||
} catch (Throwable e) {
|
||||
log.error("[syncRefund][refund({}) 同步退款状态异常]", refund.getId(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得自身的代理对象,解决 AOP 生效问题
|
||||
*
|
||||
* @return 自己
|
||||
*/
|
||||
private PayRefundServiceImpl getSelf() {
|
||||
return SpringUtil.getBean(getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,9 +20,11 @@ import org.springframework.context.annotation.Import;
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Validator;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
@ -68,7 +70,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
|
||||
public void testRefreshLocalCache() {
|
||||
// mock 数据 01
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class,
|
||||
o -> o.setConfig(randomWxPayClientConfig()));
|
||||
o -> o.setConfig(randomWxPayClientConfig()).setUpdateTime(addTime(Duration.ofMinutes(-2))));
|
||||
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
|
||||
channelService.initLocalCache();
|
||||
// mock 数据 02
|
||||
|
@ -30,13 +30,13 @@ import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
||||
@ -44,8 +44,7 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -85,6 +84,51 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
||||
when(properties.getOrderNotifyUrl()).thenReturn("http://127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrder_id() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class);
|
||||
orderMapper.insert(order);
|
||||
// 准备参数
|
||||
Long id = order.getId();
|
||||
|
||||
// 调用
|
||||
PayOrderDO dbOrder = orderService.getOrder(id);
|
||||
// 断言
|
||||
assertPojoEquals(dbOrder, order);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrder_appIdAndMerchantOrderId() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class);
|
||||
orderMapper.insert(order);
|
||||
// 准备参数
|
||||
Long appId = order.getAppId();
|
||||
String merchantOrderId = order.getMerchantOrderId();
|
||||
|
||||
// 调用
|
||||
PayOrderDO dbOrder = orderService.getOrder(appId, merchantOrderId);
|
||||
// 断言
|
||||
assertPojoEquals(dbOrder, order);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrderCountByAppId() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order01 = randomPojo(PayOrderDO.class);
|
||||
orderMapper.insert(order01);
|
||||
PayOrderDO order02 = randomPojo(PayOrderDO.class);
|
||||
orderMapper.insert(order02);
|
||||
// 准备参数
|
||||
Long appId = order01.getAppId();
|
||||
|
||||
// 调用
|
||||
Long count = orderService.getOrderCountByAppId(appId);
|
||||
// 断言
|
||||
assertEquals(count, 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrderPage() {
|
||||
// mock 数据
|
||||
@ -224,7 +268,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
||||
@Test
|
||||
public void testSubmitOrder_notWaiting() {
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()));
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.REFUND.getStatus()));
|
||||
orderMapper.insert(order);
|
||||
// 准备参数
|
||||
PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId()));
|
||||
@ -234,6 +278,19 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
||||
assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubmitOrder_isSuccess() {
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()));
|
||||
orderMapper.insert(order);
|
||||
// 准备参数
|
||||
PayOrderSubmitReqVO reqVO = randomPojo(PayOrderSubmitReqVO.class, o -> o.setId(order.getId()));
|
||||
String userIp = randomString();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_STATUS_IS_SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubmitOrder_expired() {
|
||||
// mock 数据(order)
|
||||
@ -350,7 +407,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
||||
// mock 方法(client)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法()
|
||||
// mock 方法(支付渠道的调用)
|
||||
PayOrderRespDTO unifiedOrderResp = randomPojo(PayOrderRespDTO.class, o -> o.setChannelErrorCode(null).setChannelErrorMsg(null)
|
||||
.setDisplayMode(PayOrderDisplayModeEnum.URL.getMode()).setDisplayContent("tudou"));
|
||||
when(client.unifiedOrder(argThat(payOrderUnifiedReqDTO -> {
|
||||
@ -383,6 +440,57 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateOrderActuallyPaid_dbPaid() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
// mock 方法(OrderExtension 已支付)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setOrderId(id).setStatus(PayOrderStatusEnum.SUCCESS.getStatus()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> orderService.validateOrderActuallyPaid(id),
|
||||
ORDER_EXTENSION_IS_PAID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateOrderActuallyPaid_remotePaid() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
// mock 方法(OrderExtension 已支付)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setOrderId(id).setStatus(PayOrderStatusEnum.WAITING.getStatus()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient 已支付)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(orderExtension.getChannelId()))).thenReturn(client);
|
||||
when(client.getOrder(eq(orderExtension.getNo()))).thenReturn(randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())));
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> orderService.validateOrderActuallyPaid(id),
|
||||
ORDER_EXTENSION_IS_PAID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateOrderActuallyPaid_success() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
// mock 方法(OrderExtension 已支付)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setOrderId(id).setStatus(PayOrderStatusEnum.WAITING.getStatus()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient 已支付)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(orderExtension.getChannelId()))).thenReturn(client);
|
||||
when(client.getOrder(eq(orderExtension.getNo()))).thenReturn(randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())));
|
||||
|
||||
// 调用,并断言异常
|
||||
orderService.validateOrderActuallyPaid(id);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOrder_channelId() {
|
||||
PayOrderServiceImpl payOrderServiceImpl = mock(PayOrderServiceImpl.class);
|
||||
@ -553,14 +661,449 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
||||
assertPojoEquals(order, orderMapper.selectOne(null),
|
||||
"updateTime", "updater");
|
||||
// 断言,调用
|
||||
verify(notifyService).createPayNotifyTask(argThat(new ArgumentMatcher<PayNotifyTaskCreateReqDTO>() {
|
||||
@Override
|
||||
public boolean matches(PayNotifyTaskCreateReqDTO reqDTO) {
|
||||
assertEquals(reqDTO.getType(), PayNotifyTypeEnum.ORDER.getType());
|
||||
assertEquals(reqDTO.getDataId(), orderExtension.getOrderId());
|
||||
return true;
|
||||
}
|
||||
verify(notifyService).createPayNotifyTask(argThat(reqDTO -> {
|
||||
assertEquals(reqDTO.getType(), PayNotifyTypeEnum.ORDER.getType());
|
||||
assertEquals(reqDTO.getDataId(), orderExtension.getOrderId());
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOrderClosed_orderExtension_notFound() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusRespEnum.CLOSED.getStatus()));
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> orderService.notifyOrder(channel, notify),
|
||||
ORDER_EXTENSION_NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOrderClosed_orderExtension_closed() {
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())
|
||||
.setNo("P110"));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusRespEnum.CLOSED.getStatus())
|
||||
.setOutTradeNo("P110"));
|
||||
|
||||
// 调用,并断言
|
||||
orderService.notifyOrder(channel, notify);
|
||||
// 断言 PayOrderExtensionDO :数据未更新,因为它是 CLOSED
|
||||
assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOrderClosed_orderExtension_paid() {
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())
|
||||
.setNo("P110"));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusRespEnum.CLOSED.getStatus())
|
||||
.setOutTradeNo("P110"));
|
||||
|
||||
// 调用,并断言
|
||||
orderService.notifyOrder(channel, notify);
|
||||
// 断言 PayOrderExtensionDO :数据未更新,因为它是 SUCCESS
|
||||
assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOrderClosed_orderExtension_refund() {
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.REFUND.getStatus())
|
||||
.setNo("P110"));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusRespEnum.CLOSED.getStatus())
|
||||
.setOutTradeNo("P110"));
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> orderService.notifyOrder(channel, notify),
|
||||
ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOrderClosed_orderExtension_waiting() {
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setNo("P110"));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusRespEnum.CLOSED.getStatus())
|
||||
.setOutTradeNo("P110"));
|
||||
|
||||
// 调用
|
||||
orderService.notifyOrder(channel, notify);
|
||||
// 断言 PayOrderExtensionDO
|
||||
orderExtension.setStatus(PayOrderStatusEnum.CLOSED.getStatus()).setChannelNotifyData(toJsonString(notify))
|
||||
.setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg());
|
||||
assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null),
|
||||
"updateTime", "updater");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateOrderRefundPrice_notFound() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
Integer incrRefundPrice = randomInteger();
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> orderService.updateOrderRefundPrice(id, incrRefundPrice),
|
||||
ORDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateOrderRefundPrice_waiting() {
|
||||
testUpdateOrderRefundPrice_waitingOrClosed(PayOrderStatusEnum.WAITING.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateOrderRefundPrice_closed() {
|
||||
testUpdateOrderRefundPrice_waitingOrClosed(PayOrderStatusEnum.CLOSED.getStatus());
|
||||
}
|
||||
|
||||
private void testUpdateOrderRefundPrice_waitingOrClosed(Integer status) {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(status));
|
||||
orderMapper.insert(order);
|
||||
// 准备参数
|
||||
Long id = order.getId();
|
||||
Integer incrRefundPrice = randomInteger();
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> orderService.updateOrderRefundPrice(id, incrRefundPrice),
|
||||
ORDER_REFUND_FAIL_STATUS_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateOrderRefundPrice_priceExceed() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())
|
||||
.setRefundPrice(1).setPrice(10));
|
||||
orderMapper.insert(order);
|
||||
// 准备参数
|
||||
Long id = order.getId();
|
||||
Integer incrRefundPrice = 10;
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> orderService.updateOrderRefundPrice(id, incrRefundPrice),
|
||||
REFUND_PRICE_EXCEED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateOrderRefundPrice_refund() {
|
||||
testUpdateOrderRefundPrice_refundOrSuccess(PayOrderStatusEnum.REFUND.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateOrderRefundPrice_success() {
|
||||
testUpdateOrderRefundPrice_refundOrSuccess(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||
}
|
||||
|
||||
private void testUpdateOrderRefundPrice_refundOrSuccess(Integer status) {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(status).setRefundPrice(1).setPrice(10));
|
||||
orderMapper.insert(order);
|
||||
// 准备参数
|
||||
Long id = order.getId();
|
||||
Integer incrRefundPrice = 8;
|
||||
|
||||
// 调用
|
||||
orderService.updateOrderRefundPrice(id, incrRefundPrice);
|
||||
// 断言
|
||||
order.setRefundPrice(9).setStatus(PayOrderStatusEnum.REFUND.getStatus());
|
||||
assertPojoEquals(order, orderMapper.selectOne(null),
|
||||
"updateTime", "updater");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrderExtension() {
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class);
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// 准备参数
|
||||
Long id = orderExtension.getId();
|
||||
|
||||
// 调用
|
||||
PayOrderExtensionDO dbOrderExtension = orderService.getOrderExtension(id);
|
||||
// 断言
|
||||
assertPojoEquals(dbOrderExtension, orderExtension);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncOrder_payClientNotFound() {
|
||||
// 准备参数
|
||||
LocalDateTime minCreateTime = LocalDateTime.now().minus(Duration.ofMinutes(10));
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setCreateTime(LocalDateTime.now()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
|
||||
// 调用
|
||||
int count = orderService.syncOrder(minCreateTime);
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncOrder_exception() {
|
||||
// 准备参数
|
||||
LocalDateTime minCreateTime = LocalDateTime.now().minus(Duration.ofMinutes(10));
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setChannelId(10L)
|
||||
.setCreateTime(LocalDateTime.now()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(PayClient 异常)
|
||||
when(client.getOrder(any())).thenThrow(new RuntimeException());
|
||||
|
||||
// 调用
|
||||
int count = orderService.syncOrder(minCreateTime);
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncOrder_orderSuccess() {
|
||||
PayOrderServiceImpl payOrderServiceImpl = mock(PayOrderServiceImpl.class);
|
||||
try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
||||
springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayOrderServiceImpl.class)))
|
||||
.thenReturn(payOrderServiceImpl);
|
||||
|
||||
// 准备参数
|
||||
LocalDateTime minCreateTime = LocalDateTime.now().minus(Duration.ofMinutes(10));
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setChannelId(10L).setNo("P110")
|
||||
.setCreateTime(LocalDateTime.now()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(PayClient 成功返回)
|
||||
PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()));
|
||||
when(client.getOrder(eq("P110"))).thenReturn(respDTO);
|
||||
// mock 方法(PayChannelDO)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
|
||||
|
||||
// 调用
|
||||
int count = orderService.syncOrder(minCreateTime);
|
||||
// 断言
|
||||
assertEquals(count, 1);
|
||||
verify(payOrderServiceImpl).notifyOrder(same(channel), same(respDTO));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncOrder_orderClosed() {
|
||||
PayOrderServiceImpl payOrderServiceImpl = mock(PayOrderServiceImpl.class);
|
||||
try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
||||
springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayOrderServiceImpl.class)))
|
||||
.thenReturn(payOrderServiceImpl);
|
||||
|
||||
// 准备参数
|
||||
LocalDateTime minCreateTime = LocalDateTime.now().minus(Duration.ofMinutes(10));
|
||||
// mock 数据(PayOrderExtensionDO)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setChannelId(10L).setNo("P110")
|
||||
.setCreateTime(LocalDateTime.now()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(PayClient 成功返回)
|
||||
PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()));
|
||||
when(client.getOrder(eq("P110"))).thenReturn(respDTO);
|
||||
// mock 方法(PayChannelDO)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
|
||||
|
||||
// 调用
|
||||
int count = orderService.syncOrder(minCreateTime);
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
verify(payOrderServiceImpl).notifyOrder(same(channel), same(respDTO));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireOrder_orderExtension_isSuccess() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setExpireTime(addTime(Duration.ofMinutes(-1))));
|
||||
orderMapper.insert(order);
|
||||
// mock 数据(PayOrderExtensionDO 已支付)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())
|
||||
.setOrderId(order.getId()));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
|
||||
// 调用
|
||||
int count = orderService.expireOrder();
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
// 断言 order 没有变化,因为没更新
|
||||
assertPojoEquals(order, orderMapper.selectOne(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireOrder_payClient_notFound() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setExpireTime(addTime(Duration.ofMinutes(-1))));
|
||||
orderMapper.insert(order);
|
||||
// mock 数据(PayOrderExtensionDO 等待中)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setOrderId(order.getId())
|
||||
.setChannelId(10L));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
|
||||
// 调用
|
||||
int count = orderService.expireOrder();
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
// 断言 order 没有变化,因为没更新
|
||||
assertPojoEquals(order, orderMapper.selectOne(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireOrder_getOrder_isRefund() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setExpireTime(addTime(Duration.ofMinutes(-1))));
|
||||
orderMapper.insert(order);
|
||||
// mock 数据(PayOrderExtensionDO 等待中)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setOrderId(order.getId()).setNo("P110")
|
||||
.setChannelId(10L));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(PayClient 退款返回)
|
||||
PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.REFUND.getStatus()));
|
||||
when(client.getOrder(eq("P110"))).thenReturn(respDTO);
|
||||
|
||||
// 调用
|
||||
int count = orderService.expireOrder();
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
// 断言 order 没有变化,因为没更新
|
||||
assertPojoEquals(order, orderMapper.selectOne(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireOrder_getOrder_isSuccess() {
|
||||
PayOrderServiceImpl payOrderServiceImpl = mock(PayOrderServiceImpl.class);
|
||||
try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
||||
springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayOrderServiceImpl.class)))
|
||||
.thenReturn(payOrderServiceImpl);
|
||||
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setExpireTime(addTime(Duration.ofMinutes(-1))));
|
||||
orderMapper.insert(order);
|
||||
// mock 数据(PayOrderExtensionDO 等待中)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setOrderId(order.getId()).setNo("P110")
|
||||
.setChannelId(10L));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(PayClient 成功返回)
|
||||
PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()));
|
||||
when(client.getOrder(eq("P110"))).thenReturn(respDTO);
|
||||
// mock 方法(PayChannelDO)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
|
||||
|
||||
// 调用
|
||||
int count = orderService.expireOrder();
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
// 断言 order 没有变化,因为没更新
|
||||
assertPojoEquals(order, orderMapper.selectOne(null));
|
||||
verify(payOrderServiceImpl).notifyOrder(same(channel), same(respDTO));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireOrder_success() {
|
||||
// mock 数据(PayOrderDO)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setExpireTime(addTime(Duration.ofMinutes(-1))));
|
||||
orderMapper.insert(order);
|
||||
// mock 数据(PayOrderExtensionDO 等待中)
|
||||
PayOrderExtensionDO orderExtension = randomPojo(PayOrderExtensionDO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setOrderId(order.getId()).setNo("P110")
|
||||
.setChannelId(10L));
|
||||
orderExtensionMapper.insert(orderExtension);
|
||||
// mock 方法(PayClient)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(PayClient 关闭返回)
|
||||
PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
|
||||
o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()));
|
||||
when(client.getOrder(eq("P110"))).thenReturn(respDTO);
|
||||
|
||||
// 调用
|
||||
int count = orderService.expireOrder();
|
||||
// 断言
|
||||
assertEquals(count, 1);
|
||||
// 断言 extension 变化
|
||||
orderExtension.setStatus(PayOrderStatusEnum.CLOSED.getStatus())
|
||||
.setChannelNotifyData(toJsonString(respDTO));
|
||||
assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null),
|
||||
"updateTime", "updater");
|
||||
// 断言 order 变化
|
||||
order.setStatus(PayOrderStatusEnum.CLOSED.getStatus());
|
||||
assertPojoEquals(order, orderMapper.selectOne(null),
|
||||
"updateTime", "updater");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,35 +1,62 @@
|
||||
package cn.iocoder.yudao.module.pay.service.refund;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
|
||||
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
|
||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
|
||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@Import(PayRefundServiceImpl.class)
|
||||
/**
|
||||
* {@link PayRefundServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Import({PayRefundServiceImpl.class, PayNoRedisDAO.class})
|
||||
public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
|
||||
|
||||
@Resource
|
||||
@ -51,50 +78,81 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
|
||||
@MockBean
|
||||
private PayNotifyService notifyService;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
when(payProperties.getRefundNotifyUrl()).thenReturn("http://127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRefund() {
|
||||
// mock 数据
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class);
|
||||
refundMapper.insert(refund);
|
||||
// 准备参数
|
||||
Long id = refund.getId();
|
||||
|
||||
// 调用
|
||||
PayRefundDO dbRefund = refundService.getRefund(id);
|
||||
// 断言
|
||||
assertPojoEquals(dbRefund, refund);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRefundCountByAppId() {
|
||||
// mock 数据
|
||||
PayRefundDO refund01 = randomPojo(PayRefundDO.class);
|
||||
refundMapper.insert(refund01);
|
||||
PayRefundDO refund02 = randomPojo(PayRefundDO.class);
|
||||
refundMapper.insert(refund02);
|
||||
// 准备参数
|
||||
Long appId = refund01.getAppId();
|
||||
|
||||
// 调用
|
||||
Long count = refundService.getRefundCountByAppId(appId);
|
||||
// 断言
|
||||
assertEquals(count, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRefundPage() {
|
||||
// mock 数据
|
||||
PayRefundDO dbRefund = randomPojo(PayRefundDO.class, o -> { // 等会查询到
|
||||
o.setAppId(1L);
|
||||
o.setChannelId(1L);
|
||||
o.setChannelCode(PayChannelEnum.WX_PUB.getCode());
|
||||
o.setOrderId(1L);
|
||||
o.setNo("OT0000001");
|
||||
o.setMerchantOrderId("MOT0000001");
|
||||
o.setMerchantRefundId("MRF0000001");
|
||||
o.setNotifyUrl("https://www.cancanzi.com");
|
||||
o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||
o.setPayPrice(100);
|
||||
o.setRefundPrice(500);
|
||||
o.setReason("就是想退款了,你有意见吗");
|
||||
o.setUserIp("127.0.0.1");
|
||||
o.setChannelOrderNo("CH0000001");
|
||||
o.setChannelRefundNo("CHR0000001");
|
||||
o.setChannelErrorCode("");
|
||||
o.setChannelErrorMsg("");
|
||||
o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
|
||||
o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
|
||||
o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
|
||||
o.setCreateTime(buildTime(2021, 1, 10));
|
||||
});
|
||||
refundMapper.insert(dbRefund);
|
||||
// 测试 appId 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setAppId(2L)));
|
||||
// 测试 channelCode 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
|
||||
// 测试 merchantRefundNo 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112")));
|
||||
// 测试 merchantOrderId 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantOrderId(randomString())));
|
||||
// 测试 merchantRefundId 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId(randomString())));
|
||||
// 测试 channelOrderNo 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelOrderNo(randomString())));
|
||||
// 测试 channelRefundNo 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelRefundNo(randomString())));
|
||||
// 测试 status 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())));
|
||||
// 测试 createTime 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
|
||||
o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setCreateTime(buildTime(2021, 1, 1))));
|
||||
// 准备参数
|
||||
PayRefundPageReqVO reqVO = new PayRefundPageReqVO();
|
||||
reqVO.setAppId(1L);
|
||||
reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
|
||||
reqVO.setMerchantOrderId("MOT0000001");
|
||||
reqVO.setMerchantRefundId("MRF0000001");
|
||||
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
||||
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
|
||||
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||
reqVO.setChannelOrderNo("CH0000001");
|
||||
reqVO.setChannelRefundNo("CHR0000001");
|
||||
reqVO.setCreateTime(buildBetweenTime(2021, 1, 9, 2021, 1, 11));
|
||||
|
||||
// 调用
|
||||
PageResult<PayRefundDO> pageResult = refundService.getRefundPage(reqVO);
|
||||
@ -109,45 +167,41 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
|
||||
// mock 数据
|
||||
PayRefundDO dbRefund = randomPojo(PayRefundDO.class, o -> { // 等会查询到
|
||||
o.setAppId(1L);
|
||||
o.setChannelId(1L);
|
||||
o.setChannelCode(PayChannelEnum.WX_PUB.getCode());
|
||||
o.setOrderId(1L);
|
||||
o.setNo("OT0000001");
|
||||
o.setMerchantOrderId("MOT0000001");
|
||||
o.setMerchantRefundId("MRF0000001");
|
||||
o.setNotifyUrl("https://www.cancanzi.com");
|
||||
o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||
o.setPayPrice(100);
|
||||
o.setRefundPrice(500);
|
||||
o.setReason("就是想退款了,你有意见吗");
|
||||
o.setUserIp("127.0.0.1");
|
||||
o.setChannelOrderNo("CH0000001");
|
||||
o.setChannelRefundNo("CHR0000001");
|
||||
o.setChannelErrorCode("");
|
||||
o.setChannelErrorMsg("");
|
||||
o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
|
||||
o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
|
||||
o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
|
||||
o.setCreateTime(buildTime(2021, 1, 10));
|
||||
});
|
||||
refundMapper.insert(dbRefund);
|
||||
// 测试 appId 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setAppId(2L)));
|
||||
// 测试 channelCode 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
|
||||
// 测试 merchantRefundNo 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112")));
|
||||
// 测试 merchantOrderId 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantOrderId(randomString())));
|
||||
// 测试 merchantRefundId 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId(randomString())));
|
||||
// 测试 channelOrderNo 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelOrderNo(randomString())));
|
||||
// 测试 channelRefundNo 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelRefundNo(randomString())));
|
||||
// 测试 status 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())));
|
||||
// 测试 createTime 不匹配
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
|
||||
o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
|
||||
|
||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setCreateTime(buildTime(2021, 1, 1))));
|
||||
// 准备参数
|
||||
PayRefundExportReqVO reqVO = new PayRefundExportReqVO();
|
||||
reqVO.setAppId(1L);
|
||||
reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
|
||||
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
||||
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
|
||||
reqVO.setMerchantOrderId("MOT0000001");
|
||||
reqVO.setMerchantRefundId("MRF0000001");
|
||||
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||
reqVO.setChannelOrderNo("CH0000001");
|
||||
reqVO.setChannelRefundNo("CHR0000001");
|
||||
reqVO.setCreateTime(buildBetweenTime(2021, 1, 9, 2021, 1, 11));
|
||||
|
||||
// 调用
|
||||
List<PayRefundDO> list = refundService.getRefundList(reqVO);
|
||||
@ -156,4 +210,495 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
|
||||
assertPojoEquals(dbRefund, list.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_orderNotFound() {
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.createPayRefund(reqDTO),
|
||||
ORDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_orderWaiting() {
|
||||
testCreateRefund_orderWaitingOrClosed(PayOrderStatusEnum.WAITING.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_orderClosed() {
|
||||
testCreateRefund_orderWaitingOrClosed(PayOrderStatusEnum.CLOSED.getStatus());
|
||||
}
|
||||
|
||||
private void testCreateRefund_orderWaitingOrClosed(Integer status) {
|
||||
// 准备参数
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L).setMerchantOrderId("100"));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o -> o.setStatus(status));
|
||||
when(orderService.getOrder(eq(1L), eq("100"))).thenReturn(order);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.createPayRefund(reqDTO),
|
||||
ORDER_REFUND_FAIL_STATUS_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_refundPriceExceed() {
|
||||
// 准备参数
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L).setMerchantOrderId("100").setPrice(10));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o ->
|
||||
o.setStatus(PayOrderStatusEnum.REFUND.getStatus())
|
||||
.setPrice(10).setRefundPrice(1));
|
||||
when(orderService.getOrder(eq(1L), eq("100"))).thenReturn(order);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.createPayRefund(reqDTO),
|
||||
REFUND_PRICE_EXCEED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_orderHasRefunding() {
|
||||
// 准备参数
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L).setMerchantOrderId("100").setPrice(10));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o ->
|
||||
o.setStatus(PayOrderStatusEnum.REFUND.getStatus())
|
||||
.setPrice(10).setRefundPrice(1));
|
||||
when(orderService.getOrder(eq(1L), eq("100"))).thenReturn(order);
|
||||
// mock 数据(refund 在退款中)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o ->
|
||||
o.setOrderId(order.getId()).setStatus(PayOrderStatusEnum.WAITING.getStatus()));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.createPayRefund(reqDTO),
|
||||
REFUND_PRICE_EXCEED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_channelNotFound() {
|
||||
// 准备参数
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L).setMerchantOrderId("100").setPrice(9));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o ->
|
||||
o.setStatus(PayOrderStatusEnum.REFUND.getStatus())
|
||||
.setPrice(10).setRefundPrice(1)
|
||||
.setChannelId(1L).setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(orderService.getOrder(eq(1L), eq("100"))).thenReturn(order);
|
||||
// mock 方法(channel)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)
|
||||
.setCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(channelService.validPayChannel(eq(1L))).thenReturn(channel);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.createPayRefund(reqDTO),
|
||||
CHANNEL_NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_refundExists() {
|
||||
// 准备参数
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L).setMerchantOrderId("100").setPrice(9)
|
||||
.setMerchantRefundId("200").setReason("测试退款"));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o ->
|
||||
o.setStatus(PayOrderStatusEnum.REFUND.getStatus())
|
||||
.setPrice(10).setRefundPrice(1)
|
||||
.setChannelId(1L).setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(orderService.getOrder(eq(1L), eq("100"))).thenReturn(order);
|
||||
// mock 方法(channel)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)
|
||||
.setCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(channelService.validPayChannel(eq(1L))).thenReturn(channel);
|
||||
// mock 方法(client)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 数据(refund 已存在)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o ->
|
||||
o.setAppId(1L).setMerchantRefundId("200"));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.createPayRefund(reqDTO),
|
||||
REFUND_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_invokeException() {
|
||||
// 准备参数
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L).setMerchantOrderId("100").setPrice(9)
|
||||
.setMerchantRefundId("200").setReason("测试退款"));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o ->
|
||||
o.setStatus(PayOrderStatusEnum.REFUND.getStatus())
|
||||
.setPrice(10).setRefundPrice(1)
|
||||
.setChannelId(10L).setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(orderService.getOrder(eq(1L), eq("100"))).thenReturn(order);
|
||||
// mock 方法(channel)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)
|
||||
.setCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
|
||||
// mock 方法(client)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(client 调用发生异常)
|
||||
when(client.unifiedRefund(any(PayRefundUnifiedReqDTO.class))).thenThrow(new RuntimeException());
|
||||
|
||||
// 调用
|
||||
Long refundId = refundService.createPayRefund(reqDTO);
|
||||
// 断言
|
||||
PayRefundDO refundDO = refundMapper.selectById(refundId);
|
||||
assertPojoEquals(reqDTO, refundDO);
|
||||
assertNotNull(refundDO.getNo());
|
||||
assertThat(refundDO)
|
||||
.extracting("orderId", "orderNo", "channelId", "channelCode",
|
||||
"notifyUrl", "channelOrderNo", "status", "payPrice", "refundPrice")
|
||||
.containsExactly(order.getId(), order.getNo(), channel.getId(), channel.getCode(),
|
||||
app.getRefundNotifyUrl(), order.getChannelOrderNo(), PayRefundStatusEnum.WAITING.getStatus(),
|
||||
order.getPrice(), reqDTO.getPrice());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefund_invokeSuccess() {
|
||||
PayRefundServiceImpl payRefundServiceImpl = mock(PayRefundServiceImpl.class);
|
||||
try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
||||
springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayRefundServiceImpl.class)))
|
||||
.thenReturn(payRefundServiceImpl);
|
||||
|
||||
// 准备参数
|
||||
PayRefundCreateReqDTO reqDTO = randomPojo(PayRefundCreateReqDTO.class,
|
||||
o -> o.setAppId(1L).setMerchantOrderId("100").setPrice(9)
|
||||
.setMerchantRefundId("200").setReason("测试退款"));
|
||||
// mock 方法(app)
|
||||
PayAppDO app = randomPojo(PayAppDO.class, o -> o.setId(1L));
|
||||
when(appService.validPayApp(eq(1L))).thenReturn(app);
|
||||
// mock 数据(order)
|
||||
PayOrderDO order = randomPojo(PayOrderDO.class, o ->
|
||||
o.setStatus(PayOrderStatusEnum.REFUND.getStatus())
|
||||
.setPrice(10).setRefundPrice(1)
|
||||
.setChannelId(10L).setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(orderService.getOrder(eq(1L), eq("100"))).thenReturn(order);
|
||||
// mock 方法(channel)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)
|
||||
.setCode(PayChannelEnum.ALIPAY_APP.getCode()));
|
||||
when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
|
||||
// mock 方法(client)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(client 成功)
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class);
|
||||
when(client.unifiedRefund(argThat(unifiedReqDTO -> {
|
||||
assertNotNull(unifiedReqDTO.getOutRefundNo());
|
||||
assertThat(unifiedReqDTO)
|
||||
.extracting("payPrice", "refundPrice", "outTradeNo",
|
||||
"notifyUrl", "reason")
|
||||
.containsExactly(order.getPrice(), reqDTO.getPrice(), order.getNo(),
|
||||
"http://127.0.0.1/10", reqDTO.getReason());
|
||||
return true;
|
||||
}))).thenReturn(refundRespDTO);
|
||||
|
||||
// 调用
|
||||
Long refundId = refundService.createPayRefund(reqDTO);
|
||||
// 断言
|
||||
PayRefundDO refundDO = refundMapper.selectById(refundId);
|
||||
assertPojoEquals(reqDTO, refundDO);
|
||||
assertNotNull(refundDO.getNo());
|
||||
assertThat(refundDO)
|
||||
.extracting("orderId", "orderNo", "channelId", "channelCode",
|
||||
"notifyUrl", "channelOrderNo", "status", "payPrice", "refundPrice")
|
||||
.containsExactly(order.getId(), order.getNo(), channel.getId(), channel.getCode(),
|
||||
app.getRefundNotifyUrl(), order.getChannelOrderNo(), PayRefundStatusEnum.WAITING.getStatus(),
|
||||
order.getPrice(), reqDTO.getPrice());
|
||||
// 断言调用
|
||||
verify(payRefundServiceImpl).notifyRefund(same(channel), same(refundRespDTO));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefund() {
|
||||
PayRefundServiceImpl payRefundServiceImpl = mock(PayRefundServiceImpl.class);
|
||||
try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
||||
springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayRefundServiceImpl.class)))
|
||||
.thenReturn(payRefundServiceImpl);
|
||||
|
||||
// 准备参数
|
||||
Long channelId = 10L;
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class);
|
||||
// mock 方法(channel)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
|
||||
|
||||
// 调用
|
||||
refundService.notifyRefund(channelId, refundRespDTO);
|
||||
// 断言
|
||||
verify(payRefundServiceImpl).notifyRefund(same(channel), same(refundRespDTO));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundSuccess_notFound() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100"));
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO),
|
||||
REFUND_NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundSuccess_isSuccess() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100"));
|
||||
// mock 数据(refund + 已支付)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100")
|
||||
.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用
|
||||
refundService.notifyRefund(channel, refundRespDTO);
|
||||
// 断言,refund 没有更新,因为已经退款成功
|
||||
assertPojoEquals(refund, refundMapper.selectById(refund.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundSuccess_failure() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100"));
|
||||
// mock 数据(refund + 已支付)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100")
|
||||
.setStatus(PayRefundStatusEnum.FAILURE.getStatus()));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO),
|
||||
REFUND_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundSuccess_updateOrderException() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100"));
|
||||
// mock 数据(refund + 已支付)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100")
|
||||
.setStatus(PayRefundStatusEnum.WAITING.getStatus())
|
||||
.setOrderId(100L).setRefundPrice(23));
|
||||
refundMapper.insert(refund);
|
||||
// mock 方法(order + 更新异常)
|
||||
doThrow(new RuntimeException()).when(orderService)
|
||||
.updateOrderRefundPrice(eq(100L), eq(23));
|
||||
|
||||
// 调用,并断言异常
|
||||
assertThrows(RuntimeException.class, () -> refundService.notifyRefund(channel, refundRespDTO));
|
||||
// 断言,refund 没有更新,因为事务回滚了
|
||||
assertPojoEquals(refund, refundMapper.selectById(refund.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundSuccess_success() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100"));
|
||||
// mock 数据(refund + 已支付)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100")
|
||||
.setStatus(PayRefundStatusEnum.WAITING.getStatus())
|
||||
.setOrderId(100L).setRefundPrice(23));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用
|
||||
refundService.notifyRefund(channel, refundRespDTO);
|
||||
// 断言,refund
|
||||
refund.setSuccessTime(refundRespDTO.getSuccessTime())
|
||||
.setChannelRefundNo(refundRespDTO.getChannelRefundNo())
|
||||
.setStatus(PayRefundStatusEnum.SUCCESS.getStatus())
|
||||
.setChannelNotifyData(toJsonString(refundRespDTO));
|
||||
assertPojoEquals(refund, refundMapper.selectById(refund.getId()),
|
||||
"updateTime", "updater");
|
||||
// 断言,调用
|
||||
verify(orderService).updateOrderRefundPrice(eq(100L), eq(23));
|
||||
verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder()
|
||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundFailure_notFound() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100"));
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO),
|
||||
REFUND_NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundFailure_isFailure() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100"));
|
||||
// mock 数据(refund + 退款失败)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100")
|
||||
.setStatus(PayRefundStatusEnum.FAILURE.getStatus()));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用
|
||||
refundService.notifyRefund(channel, refundRespDTO);
|
||||
// 断言,refund 没有更新,因为已经退款失败
|
||||
assertPojoEquals(refund, refundMapper.selectById(refund.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundFailure_isSuccess() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100"));
|
||||
// mock 数据(refund + 已支付)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100")
|
||||
.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO),
|
||||
REFUND_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyRefundFailure_success() {
|
||||
// 准备参数
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L));
|
||||
PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class,
|
||||
o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100"));
|
||||
// mock 数据(refund + 已支付)
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100")
|
||||
.setStatus(PayRefundStatusEnum.WAITING.getStatus())
|
||||
.setOrderId(100L).setRefundPrice(23));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用
|
||||
refundService.notifyRefund(channel, refundRespDTO);
|
||||
// 断言,refund
|
||||
refund.setChannelRefundNo(refundRespDTO.getChannelRefundNo())
|
||||
.setStatus(PayRefundStatusEnum.FAILURE.getStatus())
|
||||
.setChannelNotifyData(toJsonString(refundRespDTO))
|
||||
.setChannelErrorCode(refundRespDTO.getChannelErrorCode())
|
||||
.setChannelErrorMsg(refundRespDTO.getChannelErrorMsg());
|
||||
assertPojoEquals(refund, refundMapper.selectById(refund.getId()),
|
||||
"updateTime", "updater");
|
||||
// 断言,调用
|
||||
verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder()
|
||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncRefund_notFound() {
|
||||
// 准备参数
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L)
|
||||
.setStatus(PayRefundStatusEnum.WAITING.getStatus()));
|
||||
refundMapper.insert(refund);
|
||||
|
||||
// 调用
|
||||
int count = refundService.syncRefund();
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncRefund_waiting() {
|
||||
assertEquals(testSyncRefund_waitingOrSuccessOrFailure(PayRefundStatusRespEnum.WAITING.getStatus()), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncRefund_success() {
|
||||
assertEquals(testSyncRefund_waitingOrSuccessOrFailure(PayRefundStatusRespEnum.SUCCESS.getStatus()), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncRefund_failure() {
|
||||
assertEquals(testSyncRefund_waitingOrSuccessOrFailure(PayRefundStatusRespEnum.FAILURE.getStatus()), 1);
|
||||
}
|
||||
|
||||
private int testSyncRefund_waitingOrSuccessOrFailure(Integer status) {
|
||||
PayRefundServiceImpl payRefundServiceImpl = mock(PayRefundServiceImpl.class);
|
||||
try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
||||
springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayRefundServiceImpl.class)))
|
||||
.thenReturn(payRefundServiceImpl);
|
||||
|
||||
// 准备参数
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setChannelId(10L)
|
||||
.setStatus(PayRefundStatusEnum.WAITING.getStatus())
|
||||
.setOrderNo("P110").setNo("R220"));
|
||||
refundMapper.insert(refund);
|
||||
// mock 方法(client)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(client 返回指定状态)
|
||||
PayRefundRespDTO respDTO = randomPojo(PayRefundRespDTO.class, o -> o.setStatus(status));
|
||||
when(client.getRefund(eq("P110"), eq("R220"))).thenReturn(respDTO);
|
||||
// mock 方法(channel)
|
||||
PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L));
|
||||
when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
|
||||
|
||||
// 调用
|
||||
return refundService.syncRefund();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncRefund_exception() {
|
||||
// 准备参数
|
||||
PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setChannelId(10L)
|
||||
.setStatus(PayRefundStatusEnum.WAITING.getStatus())
|
||||
.setOrderNo("P110").setNo("R220"));
|
||||
refundMapper.insert(refund);
|
||||
// mock 方法(client)
|
||||
PayClient client = mock(PayClient.class);
|
||||
when(payClientFactory.getPayClient(eq(10L))).thenReturn(client);
|
||||
// mock 方法(client 抛出异常)
|
||||
when(client.getRefund(eq("P110"), eq("R220"))).thenThrow(new RuntimeException());
|
||||
|
||||
// 调用
|
||||
int count = refundService.syncRefund();
|
||||
// 断言
|
||||
assertEquals(count, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS "pay_app" (
|
||||
"name" varchar(64) NOT NULL,
|
||||
"status" tinyint NOT NULL,
|
||||
"remark" varchar(255) DEFAULT NULL,
|
||||
`pay_notify_url` varchar(1024) NOT NULL,
|
||||
`order_notify_url` varchar(1024) NOT NULL,
|
||||
`refund_notify_url` varchar(1024) NOT NULL,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
@ -82,29 +82,26 @@ CREATE TABLE IF NOT EXISTS `pay_order_extension` (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pay_refund` (
|
||||
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
`no` varchar(64) NOT NULL,
|
||||
`app_id` bigint(20) NOT NULL,
|
||||
`channel_id` bigint(20) NOT NULL,
|
||||
`channel_code` varchar(32) NOT NULL,
|
||||
`order_id` bigint(20) NOT NULL,
|
||||
`trade_no` varchar(64) NOT NULL,
|
||||
`order_no` varchar(64) NOT NULL,
|
||||
`merchant_order_id` varchar(64) NOT NULL,
|
||||
`merchant_refund_no` varchar(64) NOT NULL,
|
||||
`merchant_refund_id` varchar(64) NOT NULL,
|
||||
`notify_url` varchar(1024) NOT NULL,
|
||||
`notify_status` tinyint(4) NOT NULL,
|
||||
`status` tinyint(4) NOT NULL,
|
||||
`type` tinyint(4) NOT NULL,
|
||||
`pay_amount` bigint(20) NOT NULL,
|
||||
`refund_amount` bigint(20) NOT NULL,
|
||||
`pay_price` bigint(20) NOT NULL,
|
||||
`refund_price` bigint(20) NOT NULL,
|
||||
`reason` varchar(256) NOT NULL,
|
||||
`user_ip` varchar(50) NULL DEFAULT NULL,
|
||||
`channel_order_no` varchar(64) NOT NULL,
|
||||
`channel_refund_no` varchar(64) NULL DEFAULT NULL,
|
||||
`success_time` datetime(0) NULL DEFAULT NULL,
|
||||
`channel_error_code` varchar(128) NULL DEFAULT NULL,
|
||||
`channel_error_msg` varchar(256) NULL DEFAULT NULL,
|
||||
`channel_extras` varchar(1024) NULL DEFAULT NULL,
|
||||
`expire_time` datetime(0) NULL DEFAULT NULL,
|
||||
`success_time` datetime(0) NULL DEFAULT NULL,
|
||||
`notify_time` datetime(0) NULL DEFAULT NULL,
|
||||
`channel_notify_data` varchar(1024) NULL,
|
||||
`creator` varchar(64) NULL DEFAULT '',
|
||||
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updater` varchar(64) NULL DEFAULT '',
|
||||
|
@ -84,6 +84,9 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
o.setParams(Lists.newArrayList("code", "op"));
|
||||
});
|
||||
when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
||||
String title = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
|
||||
.thenReturn(title);
|
||||
String content = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
|
||||
.thenReturn(content);
|
||||
@ -101,7 +104,7 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
assertEquals(mailLogId, resultMailLogId);
|
||||
// 断言调用
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(user.getEmail()),
|
||||
eq(account.getId()), eq(template.getNickname()), eq(template.getTitle()), eq(content));
|
||||
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -122,6 +125,9 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
o.setParams(Lists.newArrayList("code", "op"));
|
||||
});
|
||||
when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
||||
String title = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
|
||||
.thenReturn(title);
|
||||
String content = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
|
||||
.thenReturn(content);
|
||||
@ -139,7 +145,7 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
assertEquals(mailLogId, resultMailLogId);
|
||||
// 断言调用
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail),
|
||||
eq(account.getId()), eq(template.getNickname()), eq(template.getTitle()), eq(content));
|
||||
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,6 +167,9 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
o.setParams(Lists.newArrayList("code", "op"));
|
||||
});
|
||||
when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
||||
String title = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
|
||||
.thenReturn(title);
|
||||
String content = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
|
||||
.thenReturn(content);
|
||||
@ -178,7 +187,7 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
assertEquals(mailLogId, resultMailLogId);
|
||||
// 断言调用
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail),
|
||||
eq(account.getId()), eq(template.getNickname()), eq(template.getTitle()), eq(content));
|
||||
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,6 +209,9 @@ class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
o.setParams(Lists.newArrayList("code", "op"));
|
||||
});
|
||||
when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
||||
String title = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
|
||||
.thenReturn(title);
|
||||
String content = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
|
||||
.thenReturn(content);
|
||||
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.service.social;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
|
||||
@ -35,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@Import(SocialUserServiceImpl.class)
|
||||
public class SocialUserServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
public class SocialUserServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private SocialUserServiceImpl socialUserService;
|
||||
|
@ -68,21 +68,21 @@
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- 商城相关模块。默认注释,保证编译速度 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-promotion-biz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-product-biz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-trade-biz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||
<!-- <artifactId>yudao-module-promotion-biz</artifactId>-->
|
||||
<!-- <version>${revision}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||
<!-- <artifactId>yudao-module-product-biz</artifactId>-->
|
||||
<!-- <version>${revision}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
||||
<!-- <artifactId>yudao-module-trade-biz</artifactId>-->
|
||||
<!-- <version>${revision}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- spring boot 配置所需依赖 -->
|
||||
<dependency>
|
||||
|
@ -180,14 +180,6 @@ export const PayDisplayModeEnum = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付类型枚举
|
||||
*/
|
||||
export const PayType = {
|
||||
WECHAT: "WECHAT",
|
||||
ALIPAY: "ALIPAY"
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付订单状态枚举
|
||||
*/
|
||||
|
@ -172,7 +172,7 @@ export default {
|
||||
this.formData = response.data;
|
||||
this.formData.config = JSON.parse(response.data.config);
|
||||
}
|
||||
this.title = this.formData.id ? '创建支付渠道' : '编辑支付渠道'
|
||||
this.title = !this.formData.id ? '创建支付渠道' : '编辑支付渠道'
|
||||
}).finally(() => {
|
||||
this.formLoading = false;
|
||||
});
|
||||
@ -257,12 +257,7 @@ export default {
|
||||
this.formData.config.rootCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
@ -1,328 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :visible.sync="transferParam.wechatOpen" :title="title" @close="close" append-to-body width="800px">
|
||||
<el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="120px"
|
||||
v-loading="transferParam.loading">
|
||||
<el-form-item label-width="180px" label="渠道费率" prop="feeRate">
|
||||
<el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
|
||||
<template slot="append">%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="公众号 APPID" prop="weChatConfig.appId">
|
||||
<el-input v-model="form.weChatConfig.appId" placeholder="请输入公众号 APPID" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="商户号" prop="weChatConfig.mchId">
|
||||
<el-input v-model="form.weChatConfig.mchId" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="渠道状态" prop="status">
|
||||
<el-radio-group v-model="form.status" size="medium">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion">
|
||||
<el-radio-group v-model="form.weChatConfig.apiVersion" size="medium">
|
||||
<el-radio v-for="dict in versionDictDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="form.weChatConfig.apiVersion === 'v2'">
|
||||
<el-form-item label-width="180px" label="商户密钥" prop="weChatConfig.mchKey">
|
||||
<el-input v-model="form.weChatConfig.mchKey" placeholder="请输入商户密钥" clearable
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_cert.p12 证书" prop="weChatConfig.keyContent">
|
||||
<el-input v-model="form.weChatConfig.keyContent" type="textarea"
|
||||
placeholder="请上传 apiclient_cert.p12 证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload :limit="1" accept=".p12" action=""
|
||||
:before-upload="p12FileBeforeUpload"
|
||||
:http-request="keyContentUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="form.weChatConfig.apiVersion === 'v3'">
|
||||
<el-form-item label-width="180px" label="API V3 密钥" prop="weChatConfig.apiV3Key">
|
||||
<el-input v-model="form.weChatConfig.apiV3Key" placeholder="请输入 API V3 密钥" clearable
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_key.perm 证书" prop="weChatConfig.privateKeyContent">
|
||||
<el-input v-model="form.weChatConfig.privateKeyContent" type="textarea"
|
||||
placeholder="请上传 apiclient_key.perm 证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateKeyContentFile">
|
||||
<el-upload ref="privateKeyContentFile"
|
||||
:limit="1"
|
||||
accept=".pem"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:http-request="privateKeyContentUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="weChatConfig.privateCertContent">
|
||||
<el-input v-model="form.weChatConfig.privateCertContent" type="textarea"
|
||||
placeholder="请上传apiclient_cert.perm证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateCertContentFile">
|
||||
<el-upload ref="privateCertContentFile"
|
||||
:limit="1"
|
||||
accept=".pem"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:http-request="privateCertContentUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label-width="180px" label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" :style="{width: '100%'}" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
|
||||
|
||||
const defaultForm = {
|
||||
code: '',
|
||||
status: null,
|
||||
remark: '',
|
||||
feeRate: null,
|
||||
appId: '',
|
||||
weChatConfig: {
|
||||
appId: '',
|
||||
mchId: '',
|
||||
apiVersion: '',
|
||||
mchKey: '',
|
||||
keyContent: '',
|
||||
privateKeyContent: '',
|
||||
privateCertContent: '',
|
||||
apiV3Key:'',
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "wechatChannelForm",
|
||||
components: {},
|
||||
props: {
|
||||
// 传输的参数
|
||||
transferParam: {
|
||||
// 加载动画
|
||||
"loading": false,
|
||||
// 是否修改
|
||||
"edit": false,
|
||||
// 是否显示
|
||||
"wechatOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title:'',
|
||||
form: JSON.parse(JSON.stringify(defaultForm)),
|
||||
rules: {
|
||||
feeRate: [{
|
||||
required: true,
|
||||
message: '请输入渠道费率',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.mchId': [{
|
||||
required: true,
|
||||
message: '请传入商户号',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.appId': [{
|
||||
required: true,
|
||||
message: '请输入公众号APPID',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
status: [{
|
||||
required: true,
|
||||
message: '渠道状态不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.apiVersion': [{
|
||||
required: true,
|
||||
message: 'API版本不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.mchKey': [{
|
||||
required: true,
|
||||
message: '请输入商户密钥',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.keyContent': [{
|
||||
required: true,
|
||||
message: '请上传 apiclient_cert.p12 证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.privateKeyContent': [{
|
||||
required: true,
|
||||
message: '请上传 apiclient_key.perm 证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.privateCertContent': [{
|
||||
required: true,
|
||||
message: '请上传 apiclient_cert.perm证 书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.apiV3Key': [{
|
||||
required: true,
|
||||
message: '请上传 api V3 密钥值',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
},
|
||||
// 渠道状态 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
|
||||
versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION),
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
transferParam: {
|
||||
deep: true, // 深度监听
|
||||
handler(newVal) {
|
||||
if (newVal.wechatOpen) {
|
||||
this.form.code = newVal.payCode;
|
||||
this.form.appId = newVal.appId;
|
||||
// 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
|
||||
if (newVal.edit && newVal.loading) {
|
||||
this.title = "编辑支付渠道";
|
||||
this.init();
|
||||
} else {
|
||||
this.title = "创建支付渠道";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
getChannel(this.transferParam.appId, this.transferParam.payCode)
|
||||
.then(response => {
|
||||
this.form.id = response.data.id;
|
||||
this.form.feeRate = response.data.feeRate;
|
||||
this.form.appId = response.data.appId;
|
||||
this.form.status = response.data.status;
|
||||
this.form.remark = response.data.remark;
|
||||
|
||||
let config = JSON.parse(response.data.config);
|
||||
this.form.weChatConfig.appId = config.appId;
|
||||
this.form.weChatConfig.apiVersion = config.apiVersion;
|
||||
this.form.weChatConfig.mchId = config.mchId;
|
||||
this.form.weChatConfig.mchKey = config.mchKey;
|
||||
this.form.weChatConfig.keyContent = config.keyContent;
|
||||
this.form.weChatConfig.privateKeyContent = config.privateKeyContent;
|
||||
this.form.weChatConfig.privateCertContent = config.privateCertContent;
|
||||
this.form.weChatConfig.apiV3Key = config.apiV3Key;
|
||||
this.transferParam.loading = false;
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.transferParam.wechatOpen = false;
|
||||
this.form = JSON.parse(JSON.stringify(defaultForm));
|
||||
},
|
||||
handleConfirm() {
|
||||
this.$refs['wechatJsApiForm'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
let data = this.form;
|
||||
data.config = JSON.stringify(this.form.weChatConfig);
|
||||
if (this.transferParam.edit) {
|
||||
updateChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.close();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
||||
createChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.$parent.refreshTable();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem 上传前的校验
|
||||
*/
|
||||
fileBeforeUpload(file, fileAccept) {
|
||||
let format = '.' + file.name.split(".")[1];
|
||||
if (format !== fileAccept) {
|
||||
debugger
|
||||
this.$message.error('请上传指定格式"' + fileAccept + '"文件');
|
||||
return false;
|
||||
}
|
||||
let isRightSize = file.size / 1024 / 1024 < 2
|
||||
if (!isRightSize) {
|
||||
this.$message.error('文件大小超过 2MB')
|
||||
}
|
||||
return isRightSize
|
||||
},
|
||||
p12FileBeforeUpload(file) {
|
||||
this.fileBeforeUpload(file, '.p12')
|
||||
},
|
||||
pemFileBeforeUpload(file) {
|
||||
this.fileBeforeUpload(file, '.pem')
|
||||
},
|
||||
/**
|
||||
* 读取 apiclient_key.pem 到 privateKeyContent 字段
|
||||
*/
|
||||
privateKeyContentUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.weChatConfig.privateKeyContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
/**
|
||||
* 读取 apiclient_cert.pem 到 privateCertContent 字段
|
||||
*/
|
||||
privateCertContentUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.weChatConfig.privateCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
/**
|
||||
* 读取 apiclient_cert.p12 到 keyContent 字段
|
||||
*/
|
||||
keyContentUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.weChatConfig.keyContent = e.target.result.split(',')[1]
|
||||
}
|
||||
readFile.readAsDataURL(event.file); // 读成 base64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :visible.sync="dialogVisible" :title="title" @close="close" append-to-body width="800px">
|
||||
<el-form ref="form" :model="formData" :rules="rules" size="medium" label-width="120px"
|
||||
v-loading="formLoading">
|
||||
<el-form-item label-width="180px" label="渠道费率" prop="feeRate">
|
||||
<el-input v-model="formData.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
|
||||
<template slot="append">%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="公众号 APPID" prop="config.appId">
|
||||
<el-input v-model="formData.config.appId" placeholder="请输入公众号 APPID" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="商户号" prop="config.mchId">
|
||||
<el-input v-model="formData.config.mchId" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="渠道状态" prop="status">
|
||||
<el-radio-group v-model="formData.status" size="medium">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)"
|
||||
:label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="API 版本" prop="config.apiVersion">
|
||||
<el-radio-group v-model="formData.config.apiVersion" size="medium">
|
||||
<el-radio label="v2">v2</el-radio>
|
||||
<el-radio label="v3">v3</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="formData.config.apiVersion === 'v2'">
|
||||
<el-form-item label-width="180px" label="商户密钥" prop="config.mchKey">
|
||||
<el-input v-model="formData.config.mchKey" placeholder="请输入商户密钥" clearable
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_cert.p12 证书" prop="config.keyContent">
|
||||
<el-input v-model="formData.config.keyContent" type="textarea"
|
||||
placeholder="请上传 apiclient_cert.p12 证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload :limit="1" accept=".p12" action=""
|
||||
:before-upload="p12FileBeforeUpload"
|
||||
:http-request="keyContentUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="formData.config.apiVersion === 'v3'">
|
||||
<el-form-item label-width="180px" label="API V3 密钥" prop="config.apiV3Key">
|
||||
<el-input v-model="formData.config.apiV3Key" placeholder="请输入 API V3 密钥" clearable
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_key.perm 证书" prop="config.privateKeyContent">
|
||||
<el-input v-model="formData.config.privateKeyContent" type="textarea"
|
||||
placeholder="请上传 apiclient_key.perm 证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateKeyContentFile">
|
||||
<el-upload ref="privateKeyContentFile"
|
||||
:limit="1"
|
||||
accept=".pem"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:http-request="privateKeyContentUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="config.privateCertContent">
|
||||
<el-input v-model="formData.config.privateCertContent" type="textarea"
|
||||
placeholder="请上传apiclient_cert.perm证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateCertContentFile">
|
||||
<el-upload ref="privateCertContentFile"
|
||||
:limit="1"
|
||||
accept=".pem"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:http-request="privateCertContentUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label-width="180px" label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" :style="{width: '100%'}" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { createChannel, getChannel, updateChannel } from "@/api/pay/channel";
|
||||
import { CommonStatusEnum } from "@/utils/constants";
|
||||
|
||||
export default {
|
||||
name: "weixinChannelForm",
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
formLoading: false,
|
||||
title:'',
|
||||
formData: {
|
||||
appId: '',
|
||||
code: '',
|
||||
status: undefined,
|
||||
feeRate: undefined,
|
||||
remark: '',
|
||||
config: {
|
||||
appId: '',
|
||||
mchId: '',
|
||||
apiVersion: '',
|
||||
mchKey: '',
|
||||
keyContent: '',
|
||||
privateKeyContent: '',
|
||||
privateCertContent: '',
|
||||
apiV3Key:'',
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
feeRate: [{ required: true, message: '请输入渠道费率', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '渠道状态不能为空', trigger: 'blur'}],
|
||||
'config.mchId': [{ required: true, message: '请传入商户号', trigger: 'blur'}],
|
||||
'config.appId': [{ required: true, message: '请输入公众号APPID', trigger: 'blur'}],
|
||||
'config.apiVersion': [{ required: true, message: 'API版本不能为空', trigger: 'blur'}],
|
||||
'config.mchKey': [{ required: true, message: '请输入商户密钥', trigger: 'blur' }],
|
||||
'config.keyContent': [{ required: true, message: '请上传 apiclient_cert.p12 证书', trigger: 'blur' }],
|
||||
'config.privateKeyContent': [{ required: true, message: '请上传 apiclient_key.perm 证书', trigger: 'blur' }],
|
||||
'config.privateCertContent': [{ required: true, message: '请上传 apiclient_cert.perm证 书', trigger: 'blur' }],
|
||||
'config.apiV3Key': [{ required: true, message: '请上传 api V3 密钥值', trigger: 'blur' }],
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open(appId, code) {
|
||||
this.dialogVisible = true;
|
||||
this.formLoading = true;
|
||||
this.reset(appId, code);
|
||||
getChannel(appId, code).then(response => {
|
||||
if (response.data && response.data.id) {
|
||||
this.formData = response.data;
|
||||
this.formData.config = JSON.parse(response.data.config);
|
||||
}
|
||||
this.title = !this.formData.id ? '创建支付渠道' : '编辑支付渠道'
|
||||
}).finally(() => {
|
||||
this.formLoading = false;
|
||||
});
|
||||
},
|
||||
close() {
|
||||
this.dialogVisible = false;
|
||||
this.reset(undefined, undefined);
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
const data = { ...this.formData };
|
||||
data.config = JSON.stringify(this.formData.config);
|
||||
if (!data.id) {
|
||||
createChannel(data).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.$emit('success')
|
||||
this.close();
|
||||
});
|
||||
} else {
|
||||
updateChannel(data).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.$emit('success')
|
||||
this.close();
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 重置表单 */
|
||||
reset(appId, code) {
|
||||
this.formData = {
|
||||
appId: appId,
|
||||
code: code,
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
feeRate: undefined,
|
||||
remark: '',
|
||||
config: {
|
||||
appId: '',
|
||||
mchId: '',
|
||||
apiVersion: '',
|
||||
mchKey: '',
|
||||
keyContent: '',
|
||||
privateKeyContent: '',
|
||||
privateCertContent: '',
|
||||
apiV3Key:'',
|
||||
}
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/**
|
||||
* apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem 上传前的校验
|
||||
*/
|
||||
fileBeforeUpload(file, fileAccept) {
|
||||
let format = '.' + file.name.split(".")[1];
|
||||
if (format !== fileAccept) {
|
||||
debugger
|
||||
this.$message.error('请上传指定格式"' + fileAccept + '"文件');
|
||||
return false;
|
||||
}
|
||||
let isRightSize = file.size / 1024 / 1024 < 2
|
||||
if (!isRightSize) {
|
||||
this.$message.error('文件大小超过 2MB')
|
||||
}
|
||||
return isRightSize
|
||||
},
|
||||
p12FileBeforeUpload(file) {
|
||||
this.fileBeforeUpload(file, '.p12')
|
||||
},
|
||||
pemFileBeforeUpload(file) {
|
||||
this.fileBeforeUpload(file, '.pem')
|
||||
},
|
||||
/**
|
||||
* 读取 apiclient_key.pem 到 privateKeyContent 字段
|
||||
*/
|
||||
privateKeyContentUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.formData.config.privateKeyContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
/**
|
||||
* 读取 apiclient_cert.pem 到 privateCertContent 字段
|
||||
*/
|
||||
privateCertContentUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.formData.config.privateCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
/**
|
||||
* 读取 apiclient_cert.p12 到 keyContent 字段
|
||||
*/
|
||||
keyContentUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.formData.config.keyContent = e.target.result.split(',')[1]
|
||||
}
|
||||
readFile.readAsDataURL(event.file); // 读成 base64
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<doc-alert title="支付功能开启" url="https://doc.iocoder.cn/pay/build/" />
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="应用名" prop="name">
|
||||
@ -9,7 +9,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable>
|
||||
<el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label"
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" :label="dict.label"
|
||||
:value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@ -43,65 +43,59 @@
|
||||
@change="handleStatusChange(scope.row)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商户名称" align="center" prop="payMerchant.name"/>
|
||||
<el-table-column label="支付宝配置" align="center">
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_APP.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_APP.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_APP.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_APP.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_PC.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_PC.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_PC.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_PC.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_WAP.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_WAP.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_WAP.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_WAP.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_QR.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_QR.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_QR.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_QR.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_BAR.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_BAR.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.ALIPAY_BAR.code)"
|
||||
@click="handleChannel(scope.row,payChannelEnum.ALIPAY_BAR.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.ALIPAY_BAR.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -110,60 +104,55 @@
|
||||
<el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_LITE.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_LITE.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_LITE.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_LITE.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_PUB.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_PUB.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_PUB.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_PUB.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_APP.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_APP.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_APP.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_APP.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_APP.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_NATIVE.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_NATIVE.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_NATIVE.code,payType.WECHAT)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_NATIVE.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_NATIVE.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_NATIVE.code,payType.WECHAT)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_NATIVE.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_BAR.name" align="center">
|
||||
<template v-slot="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_BAR.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_BAR.code,payType.WECHAT)">
|
||||
v-if="isChannelExists(scope.row.channelCodes, payChannelEnum.WX_BAR.code)"
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_BAR.code)">
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_BAR.code,payType.WECHAT)">
|
||||
<el-button v-else type="danger" icon="el-icon-close" circle
|
||||
@click="handleChannel(scope.row, payChannelEnum.WX_BAR.code)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -191,7 +180,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
@ -214,24 +203,23 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<wechat-channel-form :transferParam="channelParam" />
|
||||
<!-- 对话框(支付应用的配置) -->
|
||||
<weixin-channel-form ref="weixinChannelFormRef" @success="getList" />
|
||||
<alipay-channel-form ref="alipayChannelFormRef" @success="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage } from "@/api/pay/app";
|
||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
|
||||
import { PayType, PayChannelEnum, CommonStatusEnum } from "@/utils/constants";
|
||||
import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm";
|
||||
import { PayChannelEnum, CommonStatusEnum } from "@/utils/constants";
|
||||
import weixinChannelForm from "@/views/pay/app/components/weixinChannelForm";
|
||||
import alipayChannelForm from "@/views/pay/app/components/alipayChannelForm";
|
||||
|
||||
export default {
|
||||
name: "PayApp",
|
||||
components: {
|
||||
"wechatChannelForm": wechatChannelForm,
|
||||
"alipayChannelForm": alipayChannelForm
|
||||
weixinChannelForm,
|
||||
alipayChannelForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -264,28 +252,8 @@ export default {
|
||||
orderNotifyUrl: [{required: true, message: "支付结果的回调地址不能为空", trigger: "blur"}],
|
||||
refundNotifyUrl: [{required: true, message: "退款结果的回调地址不能为空", trigger: "blur"}],
|
||||
},
|
||||
// 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
|
||||
sysCommonStatusEnum: CommonStatusEnum,
|
||||
// 支付渠道枚举
|
||||
payChannelEnum: PayChannelEnum,
|
||||
// 支付类型
|
||||
payType: PayType,
|
||||
// 是否显示支付窗口
|
||||
payOpen: false,
|
||||
// 微信组件传参参数
|
||||
channelParam: {
|
||||
// 是否修改
|
||||
"edit": false,
|
||||
// 微信是否显示
|
||||
"wechatOpen": false,
|
||||
// 支付宝是否显示
|
||||
"aliPayOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@ -312,7 +280,7 @@ export default {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
status: undefined,
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
remark: undefined,
|
||||
orderNotifyUrl: undefined,
|
||||
refundNotifyUrl: undefined,
|
||||
@ -397,43 +365,25 @@ export default {
|
||||
/**
|
||||
* 修改支付渠道信息
|
||||
*/
|
||||
handleUpdateChannel(row, payCode, type) {
|
||||
this.settingChannelParam(row, payCode, type)
|
||||
this.channelParam.edit = true;
|
||||
this.channelParam.loading = true;
|
||||
},
|
||||
/**
|
||||
* 新增支付渠道信息
|
||||
*/
|
||||
handleCreateChannel(row, payCode, type) {
|
||||
this.settingChannelParam(row, payCode, type)
|
||||
this.channelParam.edit = false;
|
||||
this.channelParam.loading = false;
|
||||
},
|
||||
/**
|
||||
* 设置支付渠道信息
|
||||
*/
|
||||
settingChannelParam(row, payCode, type) {
|
||||
if (type === PayType.WECHAT) {
|
||||
this.channelParam.wechatOpen = true;
|
||||
this.channelParam.aliPayOpen = false;
|
||||
handleChannel(row, code) {
|
||||
if (code.indexOf('alipay_') === 0) {
|
||||
this.$refs['alipayChannelFormRef'].open(row.id, code);
|
||||
return
|
||||
}
|
||||
if (type === PayType.ALIPAY) {
|
||||
console.log(this.$refs['alipayChannelFormRef'])
|
||||
this.$refs['alipayChannelFormRef'].open(row.id, payCode);
|
||||
return;
|
||||
// this.channelParam.aliPayOpen = true;
|
||||
// this.channelParam.wechatOpen = false;
|
||||
if (code.indexOf('wx_') === 0) {
|
||||
this.$refs['weixinChannelFormRef'].open(row.id, code);
|
||||
return
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 根据渠道编码判断渠道列表中是否存在
|
||||
*
|
||||
* @param channels 渠道列表
|
||||
* @param channelCode 渠道编码
|
||||
*/
|
||||
judgeChannelExist(channels, channelCode) {
|
||||
return channels.indexOf(channelCode) !== -1;
|
||||
isChannelExists(channels, channelCode) {
|
||||
return channels && channels.indexOf(channelCode) !== -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
@ -78,7 +78,6 @@
|
||||
</template>
|
||||
<script>
|
||||
import QrcodeVue from 'qrcode.vue'
|
||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
|
||||
import { getOrder, submitOrder } from '@/api/pay/order';
|
||||
import { PayChannelEnum, PayDisplayModeEnum, PayOrderStatusEnum } from "@/utils/constants";
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="支付宝支付接入" url="https://doc.iocoder.cn/pay/alipay-pay-demo/" />
|
||||
<doc-alert title="支付宝、微信退款接入" url="https://doc.iocoder.cn/pay/refund-demo/" />
|
||||
<doc-alert title="微信公众号支付接入" url="https://doc.iocoder.cn/pay/wx-pub-pay-demo/" />
|
||||
<doc-alert title="微信小程序支付接入" url="https://doc.iocoder.cn/pay/wx-lite-pay-demo/" />
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="支付功能开启" url="https://doc.iocoder.cn/pay/build/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||
|
@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="支付宝支付接入" url="https://doc.iocoder.cn/pay/alipay-pay-demo/" />
|
||||
<doc-alert title="微信公众号支付接入" url="https://doc.iocoder.cn/pay/wx-pub-pay-demo/" />
|
||||
<doc-alert title="微信小程序支付接入" url="https://doc.iocoder.cn/pay/wx-lite-pay-demo/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="支付宝、微信退款接入" url="https://doc.iocoder.cn/pay/refund-demo/" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
||||
<el-form-item label="应用编号" prop="appId">
|
||||
|
Loading…
Reference in New Issue
Block a user