完成订单的分账逻辑
This commit is contained in:
parent
ad2afc150b
commit
fa6e00c3ee
|
|
@ -5,7 +5,7 @@
|
|||
-- 权限表
|
||||
DROP TABLE IF EXISTS `t_sys_entitlement`;
|
||||
CREATE TABLE `t_sys_entitlement` (
|
||||
`ent_id` VARCHAR(32) NOT NULL COMMENT '权限ID[ENT_功能模块_子模块_操作], eg: ENT_ROLE_LIST_ADD',
|
||||
`ent_id` VARCHAR(64) NOT NULL COMMENT '权限ID[ENT_功能模块_子模块_操作], eg: ENT_ROLE_LIST_ADD',
|
||||
`ent_name` VARCHAR(32) NOT NULL COMMENT '权限名称',
|
||||
`menu_icon` VARCHAR(32) COMMENT '菜单图标',
|
||||
`menu_uri` VARCHAR(128) COMMENT '菜单uri/路由地址',
|
||||
|
|
@ -261,7 +261,6 @@ CREATE TABLE `t_pay_order` (
|
|||
`amount` BIGINT(20) NOT NULL COMMENT '支付金额,单位分',
|
||||
`mch_fee_rate` decimal(20,6) NOT NULL COMMENT '商户手续费费率快照',
|
||||
`mch_fee_amount` BIGINT(20) NOT NULL COMMENT '商户手续费,单位分',
|
||||
`mch_income_amount` BIGINT(20) NOT NULL COMMENT '商户入账金额(支付金额-手续费),单位分',
|
||||
`currency` VARCHAR(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny',
|
||||
`state` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '支付状态: 0-订单生成, 1-支付中, 2-支付成功, 3-支付失败, 4-已撤销, 5-已退款, 6-订单关闭',
|
||||
`notify_state` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '向下游回调状态, 0-未发送, 1-已发送',
|
||||
|
|
@ -403,13 +402,27 @@ CREATE TABLE `t_transfer_order` (
|
|||
INDEX(`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='转账订单表';
|
||||
|
||||
-- 商户分账接收者账号组
|
||||
DROP TABLE IF EXISTS `t_mch_division_receiver_group`;
|
||||
CREATE TABLE `t_mch_division_receiver_group` (
|
||||
`receiver_group_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '组ID',
|
||||
`receiver_group_name` VARCHAR(64) NOT NULL COMMENT '组名称',
|
||||
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
|
||||
`auto_division_flag` TINYINT(6) NOT NULL DEFAULT 0 COMMENT '自动分账组(当订单分账模式为自动分账,改组将完成分账逻辑) 0-否 1-是',
|
||||
`created_uid` BIGINT(20) NOT NULL COMMENT '创建者用户ID',
|
||||
`created_by` VARCHAR(64) NOT NULL COMMENT '创建者姓名',
|
||||
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
PRIMARY KEY (`receiver_group_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb4 COMMENT='分账账号组';
|
||||
|
||||
-- 商户分账接收者账号绑定关系表
|
||||
DROP TABLE IF EXISTS `t_mch_division_receiver`;
|
||||
CREATE TABLE `t_mch_division_receiver` (
|
||||
`receiver_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '分账接收者ID',
|
||||
`receiver_group_id` BIGINT(20) NOT NULL COMMENT '多渠道组合ID(便于商户接口使用)',
|
||||
`receiver_name` VARCHAR(64) NOT NULL COMMENT '接收者账号别名',
|
||||
`receiver_alias` VARCHAR(64) NOT NULL COMMENT '接收者账号别名',
|
||||
`receiver_group_id` BIGINT(20) COMMENT '组ID(便于商户接口使用)',
|
||||
`receiver_group_name` VARCHAR(64) COMMENT '组名称',
|
||||
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
|
||||
`isv_no` VARCHAR(64) COMMENT '服务商号',
|
||||
`app_id` VARCHAR(64) NOT NULL COMMENT '应用ID',
|
||||
|
|
@ -421,14 +434,13 @@ CREATE TABLE `t_mch_division_receiver` (
|
|||
`relation_type_name` VARCHAR(30) NOT NULL COMMENT '当选择自定义时,需要录入该字段。 否则为对应的名称',
|
||||
`division_profit` DECIMAL(20,6) COMMENT '分账比例',
|
||||
`state` TINYINT(6) NOT NULL COMMENT '分账状态(本系统状态,并不调用上游关联关系): 1-正常分账, 0-暂停分账',
|
||||
`channel_bind_state` TINYINT(6) NOT NULL COMMENT '上游绑定状态: 1-绑定成功, 2-绑定异常',
|
||||
`channel_bind_result` TEXT COMMENT '上游绑定返回信息,一般用作查询绑定异常时的记录',
|
||||
`channel_bind_result` TEXT COMMENT '上游绑定返回信息,一般用作查询账号异常时的记录',
|
||||
`channel_ext_info` TEXT COMMENT '渠道特殊信息',
|
||||
`bind_success_time` DATETIME DEFAULT NULL COMMENT '绑定成功时间',
|
||||
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
PRIMARY KEY (`receiver_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='商户分账接收者账号绑定关系表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=800001 DEFAULT CHARSET=utf8mb4 COMMENT='商户分账接收者账号绑定关系表';
|
||||
|
||||
-- 分账记录表
|
||||
DROP TABLE IF EXISTS `t_pay_order_division_record`;
|
||||
|
|
@ -449,7 +461,8 @@ CREATE TABLE `t_pay_order_division_record` (
|
|||
`state` TINYINT(6) NOT NULL COMMENT '状态: 0-待分账 1-分账成功, 2-分账失败',
|
||||
`channel_resp_result` TEXT COMMENT '上游返回数据包',
|
||||
`receiver_id` BIGINT(20) NOT NULL COMMENT '账号快照》 分账接收者ID',
|
||||
`receiver_group_id` BIGINT(20) NOT NULL COMMENT '账号快照》 多渠道组合ID(便于商户存储)',
|
||||
`receiver_group_id` BIGINT(20) COMMENT '账号快照》 组ID(便于商户接口使用)',
|
||||
`receiver_alias` VARCHAR(64) COMMENT '接收者账号别名',
|
||||
`acc_type` TINYINT(6) NOT NULL COMMENT '账号快照》 分账接收账号类型: 0-个人 1-商户',
|
||||
`acc_no` VARCHAR(50) NOT NULL COMMENT '账号快照》 分账接收账号',
|
||||
`acc_name` VARCHAR(30) NOT NULL DEFAULT '' COMMENT '账号快照》 分账接收账号名称',
|
||||
|
|
@ -630,6 +643,24 @@ insert into t_sys_entitlement values('ENT_ORDER', '订单中心', 'transaction',
|
|||
insert into t_sys_entitlement values('ENT_TRANSFER_ORDER_LIST', '页面:转账订单列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_TRANSFER_ORDER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_TRANSFER_ORDER_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_TRANSFER_ORDER', '0', 'MCH', now(), now());
|
||||
|
||||
-- 【商户系统】 分账管理
|
||||
insert into t_sys_entitlement values('ENT_DIVISION', '分账管理', 'apartment', '', 'RouteView', 'ML', 0, 1, 'ROOT', '30', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP', '账号组管理', 'team', '/divisionReceiverGroup', 'DivisionReceiverGroupPage', 'ML', 0, 1, 'ENT_DIVISION', '10', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_LIST', '页面:数据列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_ADD', '按钮:新增', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_EDIT', '按钮:修改', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_DELETE', '按钮:删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER', '收款账号管理', 'trademark', '/divisionReceiver', 'DivisionReceiverPage', 'ML', 0, 1, 'ENT_DIVISION', '20', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_LIST', '页面:数据列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_ADD', '按钮:新增收款账号', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_DELETE', '按钮:删除收款账号', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_EDIT', '按钮:修改账号信息', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECORD', '分账记录', 'unordered-list', '/divisionRecord', 'DivisionRecordPage', 'ML', 0, 1, 'ENT_DIVISION', '30', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECORD_LIST', '页面:数据列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECORD', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECORD_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECORD', '0', 'MCH', now(), now());
|
||||
|
||||
-- 【商户系统】 系统管理
|
||||
insert into t_sys_entitlement values('ENT_SYS_CONFIG', '系统管理', 'setting', '', 'RouteView', 'ML', 0, 1, 'ROOT', '200', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_UR', '用户角色管理', 'team', '', 'RouteView', 'ML', 0, 1, 'ENT_SYS_CONFIG', '10', 'MCH', now(), now());
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ insert into t_sys_entitlement values('ENT_MCH_TRANSFER_DO', '按钮:发起转
|
|||
|
||||
## -- ++++ ++++
|
||||
|
||||
## -- ++++ [v1.6.0] ===> [未确定] ++++
|
||||
## -- ++++ [v1.6.0] ===> [v1.7.0] ++++
|
||||
|
||||
-- 订单页的支付方式筛选项添加权限并可分配: 避免API权限导致页面出现异常
|
||||
insert into t_sys_entitlement values('ENT_PAY_ORDER_SEARCH_PAY_WAY', '筛选项:支付方式', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PAY_ORDER', '0', 'MGR', now(), now());
|
||||
|
|
@ -105,10 +105,8 @@ insert into t_sys_entitlement values('ENT_PAY_ORDER_SEARCH_PAY_WAY', '筛选项
|
|||
-- 插入表结构,并插入默认数据(默认费率 0)
|
||||
alter table `t_pay_order` add column `mch_fee_rate` decimal(20,6) NOT NULL COMMENT '商户手续费费率快照' after `amount`;
|
||||
alter table `t_pay_order` add column `mch_fee_amount` BIGINT(20) NOT NULL COMMENT '商户手续费,单位分' after `mch_fee_rate`;
|
||||
alter table `t_pay_order` add column `mch_income_amount` BIGINT(20) NOT NULL COMMENT '商户入账金额(支付金额-手续费),单位分' after `mch_fee_amount`;
|
||||
update `t_pay_order` set mch_fee_rate = 0;
|
||||
update `t_pay_order` set mch_fee_amount = 0;
|
||||
update `t_pay_order` set mch_income_amount = amount - mch_fee_amount;
|
||||
|
||||
alter table `t_pay_order` drop column `division_flag`;
|
||||
alter table `t_pay_order` drop column `division_time`;
|
||||
|
|
@ -117,7 +115,100 @@ alter table `t_pay_order` add column `division_mode` TINYINT(6) DEFAULT 0 COMMEN
|
|||
alter table `t_pay_order` add column `division_state` TINYINT(6) DEFAULT 0 COMMENT '订单分账状态:0-未发生分账, 1-等待分账任务处理, 2-分账处理中, 3-分账任务已结束(不体现状态)' after `division_mode`;
|
||||
alter table `t_pay_order` add column `division_last_time` DATETIME COMMENT '最新分账时间' after `division_state`;
|
||||
|
||||
-- TODO 分账的两张表
|
||||
|
||||
-- 商户分账接收者账号组
|
||||
DROP TABLE IF EXISTS `t_mch_division_receiver_group`;
|
||||
CREATE TABLE `t_mch_division_receiver_group` (
|
||||
`receiver_group_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '组ID',
|
||||
`receiver_group_name` VARCHAR(64) NOT NULL COMMENT '组名称',
|
||||
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
|
||||
`auto_division_flag` TINYINT(6) NOT NULL DEFAULT 0 COMMENT '自动分账组(当订单分账模式为自动分账,改组将完成分账逻辑) 0-否 1-是',
|
||||
`created_uid` BIGINT(20) NOT NULL COMMENT '创建者用户ID',
|
||||
`created_by` VARCHAR(64) NOT NULL COMMENT '创建者姓名',
|
||||
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
PRIMARY KEY (`receiver_group_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb4 COMMENT='分账账号组';
|
||||
|
||||
-- 商户分账接收者账号绑定关系表
|
||||
DROP TABLE IF EXISTS `t_mch_division_receiver`;
|
||||
CREATE TABLE `t_mch_division_receiver` (
|
||||
`receiver_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '分账接收者ID',
|
||||
`receiver_alias` VARCHAR(64) NOT NULL COMMENT '接收者账号别名',
|
||||
`receiver_group_id` BIGINT(20) COMMENT '组ID(便于商户接口使用)',
|
||||
`receiver_group_name` VARCHAR(64) COMMENT '组名称',
|
||||
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
|
||||
`isv_no` VARCHAR(64) COMMENT '服务商号',
|
||||
`app_id` VARCHAR(64) NOT NULL COMMENT '应用ID',
|
||||
`if_code` VARCHAR(20) NOT NULL COMMENT '支付接口代码',
|
||||
`acc_type` TINYINT(6) NOT NULL COMMENT '分账接收账号类型: 0-个人(对私) 1-商户(对公)',
|
||||
`acc_no` VARCHAR(50) NOT NULL COMMENT '分账接收账号',
|
||||
`acc_name` VARCHAR(30) NOT NULL DEFAULT '' COMMENT '分账接收账号名称',
|
||||
`relation_type` VARCHAR(30) NOT NULL COMMENT '分账关系类型(参考微信), 如: SERVICE_PROVIDER 服务商等',
|
||||
`relation_type_name` VARCHAR(30) NOT NULL COMMENT '当选择自定义时,需要录入该字段。 否则为对应的名称',
|
||||
`division_profit` DECIMAL(20,6) COMMENT '分账比例',
|
||||
`state` TINYINT(6) NOT NULL COMMENT '分账状态(本系统状态,并不调用上游关联关系): 1-正常分账, 0-暂停分账',
|
||||
`channel_bind_result` TEXT COMMENT '上游绑定返回信息,一般用作查询账号异常时的记录',
|
||||
`channel_ext_info` TEXT COMMENT '渠道特殊信息',
|
||||
`bind_success_time` DATETIME DEFAULT NULL COMMENT '绑定成功时间',
|
||||
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
PRIMARY KEY (`receiver_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=800001 DEFAULT CHARSET=utf8mb4 COMMENT='商户分账接收者账号绑定关系表';
|
||||
|
||||
-- 分账记录表
|
||||
DROP TABLE IF EXISTS `t_pay_order_division_record`;
|
||||
CREATE TABLE `t_pay_order_division_record` (
|
||||
`record_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分账记录ID',
|
||||
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
|
||||
`isv_no` VARCHAR(64) COMMENT '服务商号',
|
||||
`app_id` VARCHAR(64) NOT NULL COMMENT '应用ID',
|
||||
`mch_name` VARCHAR(30) NOT NULL COMMENT '商户名称',
|
||||
`mch_type` TINYINT(6) NOT NULL COMMENT '类型: 1-普通商户, 2-特约商户(服务商模式)',
|
||||
`if_code` VARCHAR(20) NOT NULL COMMENT '支付接口代码',
|
||||
`pay_order_id` VARCHAR(30) NOT NULL COMMENT '系统支付订单号',
|
||||
`pay_order_channel_order_no` VARCHAR(64) COMMENT '支付订单渠道支付订单号',
|
||||
`pay_order_amount` BIGINT(20) NOT NULL COMMENT '订单金额,单位分',
|
||||
`pay_order_division_amount` BIGINT(20) NOT NULL COMMENT '订单实际分账金额, 单位:分(订单金额 - 商户手续费 - 已退款金额)',
|
||||
`batch_order_id` VARCHAR(30) NOT NULL COMMENT '系统分账批次号',
|
||||
`channel_batch_order_id` VARCHAR(64) COMMENT '上游分账批次号',
|
||||
`state` TINYINT(6) NOT NULL COMMENT '状态: 0-待分账 1-分账成功, 2-分账失败',
|
||||
`channel_resp_result` TEXT COMMENT '上游返回数据包',
|
||||
`receiver_id` BIGINT(20) NOT NULL COMMENT '账号快照》 分账接收者ID',
|
||||
`receiver_group_id` BIGINT(20) COMMENT '账号快照》 组ID(便于商户接口使用)',
|
||||
`receiver_alias` VARCHAR(64) COMMENT '接收者账号别名',
|
||||
`acc_type` TINYINT(6) NOT NULL COMMENT '账号快照》 分账接收账号类型: 0-个人 1-商户',
|
||||
`acc_no` VARCHAR(50) NOT NULL COMMENT '账号快照》 分账接收账号',
|
||||
`acc_name` VARCHAR(30) NOT NULL DEFAULT '' COMMENT '账号快照》 分账接收账号名称',
|
||||
`relation_type` VARCHAR(30) NOT NULL COMMENT '账号快照》 分账关系类型(参考微信), 如: SERVICE_PROVIDER 服务商等',
|
||||
`relation_type_name` VARCHAR(30) NOT NULL COMMENT '账号快照》 当选择自定义时,需要录入该字段。 否则为对应的名称',
|
||||
`division_profit` DECIMAL(20,6) NOT NULL COMMENT '账号快照》 配置的实际分账比例',
|
||||
`cal_division_amount` BIGINT(20) NOT NULL COMMENT '计算该接收方的分账金额,单位分',
|
||||
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
PRIMARY KEY (`record_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='分账记录表';
|
||||
|
||||
-- 权限表扩容
|
||||
alter table `t_sys_entitlement` modify column `ent_id` VARCHAR(64) NOT NULL COMMENT '权限ID[ENT_功能模块_子模块_操作], eg: ENT_ROLE_LIST_ADD';
|
||||
|
||||
-- 【商户系统】 分账管理
|
||||
insert into t_sys_entitlement values('ENT_DIVISION', '分账管理', 'apartment', '', 'RouteView', 'ML', 0, 1, 'ROOT', '30', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP', '账号组管理', 'team', '/divisionReceiverGroup', 'DivisionReceiverGroupPage', 'ML', 0, 1, 'ENT_DIVISION', '10', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_LIST', '页面:数据列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_ADD', '按钮:新增', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_EDIT', '按钮:修改', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_GROUP_DELETE', '按钮:删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER_GROUP', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER', '收款账号管理', 'trademark', '/divisionReceiver', 'DivisionReceiverPage', 'ML', 0, 1, 'ENT_DIVISION', '20', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_LIST', '页面:数据列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_ADD', '按钮:新增收款账号', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_DELETE', '按钮:删除收款账号', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECEIVER_EDIT', '按钮:修改账号信息', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECEIVER', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECORD', '分账记录', 'unordered-list', '/divisionRecord', 'DivisionRecordPage', 'ML', 0, 1, 'ENT_DIVISION', '30', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECORD_LIST', '页面:数据列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECORD', '0', 'MCH', now(), now());
|
||||
insert into t_sys_entitlement values('ENT_DIVISION_RECORD_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_DIVISION_RECORD', '0', 'MCH', now(), now());
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ public class PayOrderDivisionMQ extends AbstractMQ {
|
|||
private Long receiverId;
|
||||
|
||||
/**
|
||||
* 多渠道组合ID(便于商户接口使用) (与 receiverId 二选一)
|
||||
* 组ID(便于商户接口使用) (与 receiverId 二选一)
|
||||
*/
|
||||
private Long receiverGroupId;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@ public class MchDivisionReceiver implements Serializable {
|
|||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
public static final byte STATE_WAIT = 0; // 待分账
|
||||
public static final byte STATE_SUCCESS = 1; // 分账成功
|
||||
public static final byte STATE_FAIL = 2; // 分账失败
|
||||
|
||||
|
||||
//gw
|
||||
public static final LambdaQueryWrapper<MchDivisionReceiver> gw(){
|
||||
return new LambdaQueryWrapper<>();
|
||||
|
|
@ -45,14 +40,19 @@ public class MchDivisionReceiver implements Serializable {
|
|||
private Long receiverId;
|
||||
|
||||
/**
|
||||
* 多渠道组合ID(便于商户接口使用)
|
||||
* 接收者账号别名
|
||||
*/
|
||||
private String receiverAlias;
|
||||
|
||||
/**
|
||||
* 组ID(便于商户接口使用)
|
||||
*/
|
||||
private Long receiverGroupId;
|
||||
|
||||
/**
|
||||
* 接收者账号别名
|
||||
* 组名称
|
||||
*/
|
||||
private String receiverName;
|
||||
private String receiverGroupName;
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
|
|
@ -109,11 +109,6 @@ public class MchDivisionReceiver implements Serializable {
|
|||
*/
|
||||
private Byte state;
|
||||
|
||||
/**
|
||||
* 上游绑定状态: 1-绑定成功, 2-绑定异常
|
||||
*/
|
||||
private Byte channelBindState;
|
||||
|
||||
/**
|
||||
* 上游绑定返回信息,一般用作查询绑定异常时的记录
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
package com.jeequan.jeepay.core.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 分账账号组
|
||||
* </p>
|
||||
*
|
||||
* @author [mybatis plus generator]
|
||||
* @since 2021-08-23
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("t_mch_division_receiver_group")
|
||||
public class MchDivisionReceiverGroup implements Serializable {
|
||||
|
||||
//gw
|
||||
public static final LambdaQueryWrapper<MchDivisionReceiverGroup> gw(){
|
||||
return new LambdaQueryWrapper<>();
|
||||
}
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
/**
|
||||
* 组ID
|
||||
*/
|
||||
@TableId(value = "receiver_group_id", type = IdType.AUTO)
|
||||
private Long receiverGroupId;
|
||||
|
||||
/**
|
||||
* 组名称
|
||||
*/
|
||||
private String receiverGroupName;
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
private String mchNo;
|
||||
|
||||
/**
|
||||
* 自动分账组(当订单分账模式为自动分账,改组将完成分账逻辑) 0-否 1-是
|
||||
*/
|
||||
private Byte autoDivisionFlag;
|
||||
|
||||
/**
|
||||
* 创建者用户ID
|
||||
*/
|
||||
private Long createdUid;
|
||||
|
||||
/**
|
||||
* 创建者姓名
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdAt;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updatedAt;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -132,11 +132,6 @@ public class PayOrder extends BaseModel implements Serializable {
|
|||
*/
|
||||
private Long mchFeeAmount;
|
||||
|
||||
/**
|
||||
* 商户入账金额(支付金额-手续费),单位分
|
||||
*/
|
||||
private Long mchIncomeAmount;
|
||||
|
||||
/**
|
||||
* 三位货币代码,人民币:cny
|
||||
*/
|
||||
|
|
@ -203,7 +198,7 @@ public class PayOrder extends BaseModel implements Serializable {
|
|||
private Byte divisionMode;
|
||||
|
||||
/**
|
||||
* 订单分账状态:0-未发生分账, 1-等待分账任务处理, 2-分账成功, 3-分账失败
|
||||
* 0-未发生分账, 1-等待分账任务处理, 2-分账处理中, 3-分账任务已结束(不体现状态)
|
||||
*/
|
||||
private Byte divisionState;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.jeequan.jeepay.core.entity;
|
|||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
|
@ -25,8 +26,16 @@ import java.util.Date;
|
|||
@TableName("t_pay_order_division_record")
|
||||
public class PayOrderDivisionRecord implements Serializable {
|
||||
|
||||
public static final byte STATE_WAIT = 0; // 待分账
|
||||
public static final byte STATE_SUCCESS = 1; // 分账成功
|
||||
public static final byte STATE_FAIL = 2; // 分账失败
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
public static final LambdaQueryWrapper<PayOrderDivisionRecord> gw(){
|
||||
return new LambdaQueryWrapper<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账记录ID
|
||||
*/
|
||||
|
|
@ -109,10 +118,15 @@ public class PayOrderDivisionRecord implements Serializable {
|
|||
private Long receiverId;
|
||||
|
||||
/**
|
||||
* 账号快照》 多渠道组合ID(便于商户存储)
|
||||
* 账号快照》 组ID(便于商户接口使用)
|
||||
*/
|
||||
private Long receiverGroupId;
|
||||
|
||||
/**
|
||||
* 账号快照》 分账接收者别名
|
||||
*/
|
||||
private String receiverAlias;
|
||||
|
||||
/**
|
||||
* 账号快照》 分账接收账号类型: 0-个人 1-商户
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -51,12 +51,12 @@ public class DBApplicationConfig implements Serializable {
|
|||
|
||||
/** 生成 【jsapi统一收银台】oauth2获取用户ID回调地址 **/
|
||||
public String genOauth2RedirectUrlEncode(String payOrderId){
|
||||
return URLUtil.encode(getPaySiteUrl() + "/cashier/index.html#/oauth2Callback/" + JeepayKit.aesEncode(payOrderId));
|
||||
return URLUtil.encodeAll(getPaySiteUrl() + "/cashier/index.html#/oauth2Callback/" + JeepayKit.aesEncode(payOrderId));
|
||||
}
|
||||
|
||||
/** 生成 【商户获取渠道用户ID接口】oauth2获取用户ID回调地址 **/
|
||||
public String genMchChannelUserIdApiOauth2RedirectUrlEncode(JSONObject param){
|
||||
return URLUtil.encode(getPaySiteUrl() + "/api/channelUserId/oauth2Callback/" + JeepayKit.aesEncode(param.toJSONString()));
|
||||
return URLUtil.encodeAll(getPaySiteUrl() + "/api/channelUserId/oauth2Callback/" + JeepayKit.aesEncode(param.toJSONString()));
|
||||
}
|
||||
|
||||
/** 生成 【jsapi统一收银台二维码图片地址】 **/
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ public class JeeUserDetails implements UserDetails {
|
|||
this.setSysUser(sysUser);
|
||||
this.setCredential(credential);
|
||||
|
||||
//TODO ....
|
||||
//做一些初始化操作
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,8 +131,22 @@ public class AmountUtil {
|
|||
* @param rate 费率 (保持与数据库的格式一致 ,真实费率值,如费率为0.55%,则传入 0.0055)
|
||||
*/
|
||||
public static Long calPercentageFee(Long amount, BigDecimal rate){
|
||||
return calPercentageFee(amount, rate, BigDecimal.ROUND_HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算百分比类型的各种费用值 (订单金额 * 真实费率 结果四舍五入并保留0位小数 )
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/8/20 14:53
|
||||
* @param amount 订单金额 (保持与数据库的格式一致 ,单位:分)
|
||||
* @param rate 费率 (保持与数据库的格式一致 ,真实费率值,如费率为0.55%,则传入 0.0055)
|
||||
* @param mode 模式 参考:BigDecimal.ROUND_HALF_UP(四舍五入) BigDecimal.ROUND_FLOOR(向下取整)
|
||||
*/
|
||||
public static Long calPercentageFee(Long amount, BigDecimal rate, int mode){
|
||||
//费率乘以订单金额 结果四舍五入并保留0位小数
|
||||
return new BigDecimal(amount).multiply(rate).setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
|
||||
return new BigDecimal(amount).multiply(rate).setScale(0, mode).longValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,10 +25,16 @@ package com.jeequan.jeepay.core.utils;
|
|||
public class RegKit {
|
||||
|
||||
public static final String REG_MOBILE = "^1\\d{10}$"; //判断是否是手机号
|
||||
public static final String REG_ALIPAY_USER_ID = "^2088\\d{12}$"; //判断是支付宝用户Id 以2088开头的纯16位数字
|
||||
|
||||
public static boolean isMobile(String str){
|
||||
return match(str, REG_MOBILE);
|
||||
}
|
||||
|
||||
public static boolean isAlipayUserId(String str){
|
||||
return match(str, REG_ALIPAY_USER_ID);
|
||||
}
|
||||
|
||||
|
||||
/** 正则验证 */
|
||||
public static boolean match(String text, String reg){
|
||||
|
|
|
|||
|
|
@ -100,6 +100,9 @@ public class PayOrderController extends CommonCtrl {
|
|||
if (StringUtils.isNotEmpty(payOrder.getAppId())) {
|
||||
wrapper.eq(PayOrder::getAppId, payOrder.getAppId());
|
||||
}
|
||||
if (payOrder.getDivisionState() != null) {
|
||||
wrapper.eq(PayOrder::getDivisionState, payOrder.getDivisionState());
|
||||
}
|
||||
if (paramJSON != null) {
|
||||
if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) {
|
||||
wrapper.ge(PayOrder::getCreatedAt, paramJSON.getString("createdStart"));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeequan.jeepay.mch.ctrl.division;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.jeequan.jeepay.JeepayClient;
|
||||
import com.jeequan.jeepay.core.aop.MethodLog;
|
||||
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApp;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiverGroup;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.ApiRes;
|
||||
import com.jeequan.jeepay.exception.JeepayException;
|
||||
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
|
||||
import com.jeequan.jeepay.model.DivisionReceiverBindReqModel;
|
||||
import com.jeequan.jeepay.request.DivisionReceiverBindRequest;
|
||||
import com.jeequan.jeepay.response.DivisionReceiverBindResponse;
|
||||
import com.jeequan.jeepay.service.impl.MchAppService;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverGroupService;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 商户分账接收者账号关系维护
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeequan.com
|
||||
* @date 2021-08-23 11:50
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/divisionReceivers")
|
||||
public class MchDivisionReceiverController extends CommonCtrl {
|
||||
|
||||
@Autowired private MchDivisionReceiverService mchDivisionReceiverService;
|
||||
@Autowired private MchDivisionReceiverGroupService mchDivisionReceiverGroupService;
|
||||
@Autowired private MchAppService mchAppService;
|
||||
@Autowired private SysConfigService sysConfigService;
|
||||
|
||||
|
||||
/** list */
|
||||
@PreAuthorize("hasAnyAuthority( 'ENT_DIVISION_RECEIVER_LIST' )")
|
||||
@RequestMapping(value="", method = RequestMethod.GET)
|
||||
public ApiRes list() {
|
||||
|
||||
MchDivisionReceiver queryObject = getObject(MchDivisionReceiver.class);
|
||||
|
||||
LambdaQueryWrapper<MchDivisionReceiver> condition = MchDivisionReceiver.gw();
|
||||
condition.eq(MchDivisionReceiver::getMchNo, getCurrentMchNo());
|
||||
|
||||
if(queryObject.getReceiverId() != null){
|
||||
condition.eq(MchDivisionReceiver::getReceiverId, queryObject.getReceiverId());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotEmpty(queryObject.getReceiverAlias())){
|
||||
condition.like(MchDivisionReceiver::getReceiverAlias, queryObject.getReceiverAlias());
|
||||
}
|
||||
|
||||
if(queryObject.getReceiverGroupId() != null){
|
||||
condition.eq(MchDivisionReceiver::getReceiverGroupId, queryObject.getReceiverGroupId());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotEmpty(queryObject.getReceiverGroupName())){
|
||||
condition.like(MchDivisionReceiver::getReceiverGroupName, queryObject.getReceiverGroupName());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotEmpty(queryObject.getAppId())){
|
||||
condition.like(MchDivisionReceiver::getAppId, queryObject.getAppId());
|
||||
}
|
||||
|
||||
if(queryObject.getState() != null){
|
||||
condition.eq(MchDivisionReceiver::getState, queryObject.getState());
|
||||
}
|
||||
|
||||
condition.orderByDesc(MchDivisionReceiver::getCreatedAt); //时间倒序
|
||||
|
||||
IPage<MchDivisionReceiver> pages = mchDivisionReceiverService.page(getIPage(true), condition);
|
||||
return ApiRes.page(pages);
|
||||
}
|
||||
|
||||
|
||||
/** detail */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_VIEW' )")
|
||||
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
|
||||
public ApiRes detail(@PathVariable("recordId") Long recordId) {
|
||||
MchDivisionReceiver record = mchDivisionReceiverService
|
||||
.getOne(MchDivisionReceiver.gw()
|
||||
.eq(MchDivisionReceiver::getMchNo, getCurrentMchNo())
|
||||
.eq(MchDivisionReceiver::getReceiverId, recordId));
|
||||
if (record == null) {
|
||||
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
|
||||
}
|
||||
return ApiRes.ok(record);
|
||||
}
|
||||
|
||||
/** add */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_ADD' )")
|
||||
@RequestMapping(value="", method = RequestMethod.POST)
|
||||
@MethodLog(remark = "新增分账接收账号")
|
||||
public ApiRes add() {
|
||||
|
||||
DivisionReceiverBindReqModel model = getObject(DivisionReceiverBindReqModel.class);
|
||||
|
||||
MchApp mchApp = mchAppService.getById(model.getAppId());
|
||||
if(mchApp == null || mchApp.getState() != CS.PUB_USABLE || !mchApp.getMchNo().equals(getCurrentMchNo()) ){
|
||||
throw new BizException("商户应用不存在或不可用");
|
||||
}
|
||||
|
||||
DivisionReceiverBindRequest request = new DivisionReceiverBindRequest();
|
||||
request.setBizModel(model);
|
||||
model.setMchNo(this.getCurrentMchNo());
|
||||
model.setAppId(mchApp.getAppId());
|
||||
model.setDivisionProfit(new BigDecimal(model.getDivisionProfit()).divide(new BigDecimal(100)).toPlainString());
|
||||
|
||||
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchApp.getAppSecret());
|
||||
|
||||
try {
|
||||
DivisionReceiverBindResponse response = jeepayClient.execute(request);
|
||||
if(response.getCode() != 0){
|
||||
throw new BizException(response.getMsg());
|
||||
}
|
||||
return ApiRes.ok(response.get());
|
||||
} catch (JeepayException e) {
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** update */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_EDIT' )")
|
||||
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
|
||||
@MethodLog(remark = "更新分账接收账号")
|
||||
public ApiRes update(@PathVariable("recordId") Long recordId) {
|
||||
|
||||
// 请求参数
|
||||
MchDivisionReceiver reqReceiver = getObject(MchDivisionReceiver.class);
|
||||
|
||||
MchDivisionReceiver record = new MchDivisionReceiver();
|
||||
record.setReceiverAlias(reqReceiver.getReceiverAlias());
|
||||
record.setReceiverGroupId(reqReceiver.getReceiverGroupId());
|
||||
record.setState(reqReceiver.getState());
|
||||
|
||||
// 改为真实比例
|
||||
if(reqReceiver.getDivisionProfit() != null){
|
||||
record.setDivisionProfit(reqReceiver.getDivisionProfit().divide(new BigDecimal(100)));
|
||||
}
|
||||
|
||||
if(record.getReceiverGroupId() != null){
|
||||
MchDivisionReceiverGroup groupRecord = mchDivisionReceiverGroupService.findByIdAndMchNo(record.getReceiverGroupId(), getCurrentMchNo());
|
||||
if (record == null) {
|
||||
throw new BizException("账号组不存在");
|
||||
}
|
||||
record.setReceiverGroupId(groupRecord.getReceiverGroupId());
|
||||
record.setReceiverGroupName(groupRecord.getReceiverGroupName());
|
||||
}
|
||||
|
||||
LambdaUpdateWrapper<MchDivisionReceiver> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(MchDivisionReceiver::getReceiverId, recordId);
|
||||
updateWrapper.eq(MchDivisionReceiver::getMchNo, getCurrentMchNo());
|
||||
mchDivisionReceiverService.update(record, updateWrapper);
|
||||
return ApiRes.ok();
|
||||
}
|
||||
|
||||
/** delete */
|
||||
@PreAuthorize("hasAuthority('ENT_DIVISION_RECEIVER_DELETE')")
|
||||
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
|
||||
@MethodLog(remark = "删除分账接收账号")
|
||||
public ApiRes del(@PathVariable("recordId") Long recordId) {
|
||||
MchDivisionReceiver record = mchDivisionReceiverService.getOne(MchDivisionReceiver.gw()
|
||||
.eq(MchDivisionReceiver::getReceiverGroupId, recordId).eq(MchDivisionReceiver::getMchNo, getCurrentMchNo()));
|
||||
if (record == null) {
|
||||
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
|
||||
}
|
||||
|
||||
mchDivisionReceiverService.removeById(recordId);
|
||||
return ApiRes.ok();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeequan.jeepay.mch.ctrl.division;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.jeequan.jeepay.core.aop.MethodLog;
|
||||
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiverGroup;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.ApiRes;
|
||||
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverGroupService;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 商户分账接收者账号组
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeequan.com
|
||||
* @date 2021-08-23 11:50
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/divisionReceiverGroups")
|
||||
public class MchDivisionReceiverGroupController extends CommonCtrl {
|
||||
|
||||
@Autowired private MchDivisionReceiverGroupService mchDivisionReceiverGroupService;
|
||||
@Autowired private MchDivisionReceiverService mchDivisionReceiverService;
|
||||
|
||||
/** list */
|
||||
@PreAuthorize("hasAnyAuthority( 'ENT_DIVISION_RECEIVER_GROUP_LIST' )")
|
||||
@RequestMapping(value="", method = RequestMethod.GET)
|
||||
public ApiRes list() {
|
||||
|
||||
MchDivisionReceiverGroup queryObject = getObject(MchDivisionReceiverGroup.class);
|
||||
|
||||
LambdaQueryWrapper<MchDivisionReceiverGroup> condition = MchDivisionReceiverGroup.gw();
|
||||
condition.eq(MchDivisionReceiverGroup::getMchNo, getCurrentMchNo());
|
||||
|
||||
if(StringUtils.isNotEmpty(queryObject.getReceiverGroupName())){
|
||||
condition.like(MchDivisionReceiverGroup::getReceiverGroupName, queryObject.getReceiverGroupName());
|
||||
}
|
||||
|
||||
if(queryObject.getReceiverGroupId() != null){
|
||||
condition.eq(MchDivisionReceiverGroup::getReceiverGroupId, queryObject.getReceiverGroupId());
|
||||
}
|
||||
|
||||
condition.orderByDesc(MchDivisionReceiverGroup::getCreatedAt); //时间倒序
|
||||
|
||||
IPage<MchDivisionReceiverGroup> pages = mchDivisionReceiverGroupService.page(getIPage(true), condition);
|
||||
return ApiRes.page(pages);
|
||||
}
|
||||
|
||||
|
||||
/** detail */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_GROUP_VIEW' )")
|
||||
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
|
||||
public ApiRes detail(@PathVariable("recordId") Long recordId) {
|
||||
MchDivisionReceiverGroup record = mchDivisionReceiverGroupService
|
||||
.getOne(MchDivisionReceiverGroup.gw()
|
||||
.eq(MchDivisionReceiverGroup::getMchNo, getCurrentMchNo())
|
||||
.eq(MchDivisionReceiverGroup::getReceiverGroupId, recordId));
|
||||
if (record == null) {
|
||||
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
|
||||
}
|
||||
return ApiRes.ok(record);
|
||||
}
|
||||
|
||||
/** add */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_GROUP_ADD' )")
|
||||
@RequestMapping(value="", method = RequestMethod.POST)
|
||||
@MethodLog(remark = "新增分账账号组")
|
||||
public ApiRes add() {
|
||||
MchDivisionReceiverGroup record = getObject(MchDivisionReceiverGroup.class);
|
||||
record.setMchNo(getCurrentMchNo());
|
||||
record.setCreatedUid(getCurrentUser().getSysUser().getSysUserId());
|
||||
record.setCreatedBy(getCurrentUser().getSysUser().getRealname());
|
||||
if(mchDivisionReceiverGroupService.save(record)){
|
||||
|
||||
//更新其他组为非默认分账组
|
||||
if(record.getAutoDivisionFlag() == CS.YES){
|
||||
mchDivisionReceiverGroupService.update(new LambdaUpdateWrapper<MchDivisionReceiverGroup>()
|
||||
.set(MchDivisionReceiverGroup::getAutoDivisionFlag, CS.NO)
|
||||
.eq(MchDivisionReceiverGroup::getMchNo, getCurrentMchNo())
|
||||
.ne(MchDivisionReceiverGroup::getReceiverGroupId, record.getReceiverGroupId())
|
||||
);
|
||||
}
|
||||
}
|
||||
return ApiRes.ok();
|
||||
}
|
||||
|
||||
/** update */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_GROUP_EDIT' )")
|
||||
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
|
||||
@MethodLog(remark = "更新分账账号组")
|
||||
public ApiRes update(@PathVariable("recordId") Long recordId) {
|
||||
|
||||
MchDivisionReceiverGroup reqRecord = getObject(MchDivisionReceiverGroup.class);
|
||||
|
||||
MchDivisionReceiverGroup record = new MchDivisionReceiverGroup();
|
||||
record.setReceiverGroupName(reqRecord.getReceiverGroupName());
|
||||
record.setAutoDivisionFlag(reqRecord.getAutoDivisionFlag());
|
||||
|
||||
LambdaUpdateWrapper<MchDivisionReceiverGroup> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(MchDivisionReceiverGroup::getReceiverGroupId, recordId);
|
||||
updateWrapper.eq(MchDivisionReceiverGroup::getMchNo, getCurrentMchNo());
|
||||
|
||||
if(mchDivisionReceiverGroupService.update(record, updateWrapper)){
|
||||
|
||||
//更新其他组为非默认分账组
|
||||
if(record.getAutoDivisionFlag() == CS.YES){
|
||||
mchDivisionReceiverGroupService.update(new LambdaUpdateWrapper<MchDivisionReceiverGroup>()
|
||||
.set(MchDivisionReceiverGroup::getAutoDivisionFlag, CS.NO)
|
||||
.eq(MchDivisionReceiverGroup::getMchNo, getCurrentMchNo())
|
||||
.ne(MchDivisionReceiverGroup::getReceiverGroupId, recordId)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return ApiRes.ok();
|
||||
}
|
||||
|
||||
/** delete */
|
||||
@PreAuthorize("hasAuthority('ENT_DIVISION_RECEIVER_GROUP_DELETE')")
|
||||
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
|
||||
@MethodLog(remark = "删除分账账号组")
|
||||
public ApiRes del(@PathVariable("recordId") Long recordId) {
|
||||
MchDivisionReceiverGroup record = mchDivisionReceiverGroupService.getOne(MchDivisionReceiverGroup.gw()
|
||||
.eq(MchDivisionReceiverGroup::getReceiverGroupId, recordId).eq(MchDivisionReceiverGroup::getMchNo, getCurrentMchNo()));
|
||||
if (record == null) {
|
||||
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
|
||||
}
|
||||
|
||||
if( mchDivisionReceiverService.count(MchDivisionReceiver.gw().eq(MchDivisionReceiver::getReceiverGroupId, recordId)) > 0){
|
||||
throw new BizException("该组存在账号,无法删除");
|
||||
}
|
||||
|
||||
mchDivisionReceiverGroupService.removeById(recordId);
|
||||
return ApiRes.ok();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeequan.jeepay.mch.ctrl.division;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.ApiRes;
|
||||
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
|
||||
import com.jeequan.jeepay.service.impl.PayOrderDivisionRecordService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 分账记录
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeequan.com
|
||||
* @date 2021-08-25 11:50
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/division/records")
|
||||
public class PayOrderDivisionRecordController extends CommonCtrl {
|
||||
|
||||
@Autowired private PayOrderDivisionRecordService payOrderDivisionRecordService;
|
||||
|
||||
|
||||
/** list */
|
||||
@PreAuthorize("hasAnyAuthority( 'ENT_DIVISION_RECORD_LIST' )")
|
||||
@RequestMapping(value="", method = RequestMethod.GET)
|
||||
public ApiRes list() {
|
||||
|
||||
PayOrderDivisionRecord queryObject = getObject(PayOrderDivisionRecord.class);
|
||||
JSONObject paramJSON = getReqParamJSON();
|
||||
|
||||
LambdaQueryWrapper<PayOrderDivisionRecord> condition = PayOrderDivisionRecord.gw();
|
||||
condition.eq(PayOrderDivisionRecord::getMchNo, getCurrentMchNo());
|
||||
|
||||
if(queryObject.getReceiverId() != null){
|
||||
condition.eq(PayOrderDivisionRecord::getReceiverId, queryObject.getReceiverId());
|
||||
}
|
||||
|
||||
if(queryObject.getReceiverGroupId() != null){
|
||||
condition.eq(PayOrderDivisionRecord::getReceiverGroupId, queryObject.getReceiverGroupId());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotEmpty(queryObject.getAppId())){
|
||||
condition.like(PayOrderDivisionRecord::getAppId, queryObject.getAppId());
|
||||
}
|
||||
|
||||
if(queryObject.getState() != null){
|
||||
condition.eq(PayOrderDivisionRecord::getState, queryObject.getState());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotEmpty(queryObject.getPayOrderId())){
|
||||
condition.eq(PayOrderDivisionRecord::getPayOrderId, queryObject.getPayOrderId());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotEmpty(queryObject.getAccNo())){
|
||||
condition.eq(PayOrderDivisionRecord::getAccNo, queryObject.getAccNo());
|
||||
}
|
||||
|
||||
if (paramJSON != null) {
|
||||
if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) {
|
||||
condition.ge(PayOrderDivisionRecord::getCreatedAt, paramJSON.getString("createdStart"));
|
||||
}
|
||||
if (StringUtils.isNotEmpty(paramJSON.getString("createdEnd"))) {
|
||||
condition.le(PayOrderDivisionRecord::getCreatedAt, paramJSON.getString("createdEnd"));
|
||||
}
|
||||
}
|
||||
|
||||
condition.orderByDesc(PayOrderDivisionRecord::getCreatedAt); //时间倒序
|
||||
|
||||
IPage<PayOrderDivisionRecord> pages = payOrderDivisionRecordService.page(getIPage(true), condition);
|
||||
return ApiRes.page(pages);
|
||||
}
|
||||
|
||||
|
||||
/** detail */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECORD_VIEW' )")
|
||||
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
|
||||
public ApiRes detail(@PathVariable("recordId") Long recordId) {
|
||||
PayOrderDivisionRecord record = payOrderDivisionRecordService
|
||||
.getOne(PayOrderDivisionRecord.gw()
|
||||
.eq(PayOrderDivisionRecord::getMchNo, getCurrentMchNo())
|
||||
.eq(PayOrderDivisionRecord::getRecordId, recordId));
|
||||
if (record == null) {
|
||||
throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
|
||||
}
|
||||
return ApiRes.ok(record);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,26 +21,22 @@ import com.jeequan.jeepay.components.mq.vender.IMQSender;
|
|||
import com.jeequan.jeepay.core.aop.MethodLog;
|
||||
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApp;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.entity.PayInterfaceConfig;
|
||||
import com.jeequan.jeepay.core.entity.PayInterfaceDefine;
|
||||
import com.jeequan.jeepay.core.entity.*;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.ApiRes;
|
||||
import com.jeequan.jeepay.core.model.params.NormalMchParams;
|
||||
import com.jeequan.jeepay.core.utils.StringKit;
|
||||
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
|
||||
import com.jeequan.jeepay.service.impl.MchAppService;
|
||||
import com.jeequan.jeepay.service.impl.MchInfoService;
|
||||
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.service.impl.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 商户支付接口配置类
|
||||
|
|
@ -180,4 +176,25 @@ public class MchPayInterfaceConfigController extends CommonCtrl {
|
|||
}
|
||||
|
||||
|
||||
/** 查询当前应用支持的支付接口 */
|
||||
@PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_ADD' )")
|
||||
@RequestMapping(value="ifCodes/{appId}", method = RequestMethod.GET)
|
||||
public ApiRes getIfCodeByAppId(@PathVariable("appId") String appId) {
|
||||
|
||||
if(mchAppService.count(MchApp.gw().eq(MchApp::getMchNo, getCurrentMchNo()).eq(MchApp::getAppId, appId)) <= 0){
|
||||
throw new BizException("商户应用不存在");
|
||||
}
|
||||
|
||||
Set<String> result = new HashSet<>();
|
||||
|
||||
payInterfaceConfigService.list(PayInterfaceConfig.gw().select(PayInterfaceConfig::getIfCode)
|
||||
.eq(PayInterfaceConfig::getState, CS.PUB_USABLE)
|
||||
.eq(PayInterfaceConfig::getInfoId, appId)
|
||||
.eq(PayInterfaceConfig::getInfoType, CS.INFO_TYPE_MCH_APP)
|
||||
).stream().forEach(r -> result.add(r.getIfCode()));
|
||||
|
||||
return ApiRes.ok(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ public class PayOrderController extends CommonCtrl {
|
|||
if (StringUtils.isNotEmpty(payOrder.getAppId())) {
|
||||
wrapper.eq(PayOrder::getAppId, payOrder.getAppId());
|
||||
}
|
||||
if (payOrder.getDivisionState() != null) {
|
||||
wrapper.eq(PayOrder::getDivisionState, payOrder.getDivisionState());
|
||||
}
|
||||
if (paramJSON != null) {
|
||||
if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) {
|
||||
wrapper.ge(PayOrder::getCreatedAt, paramJSON.getString("createdStart"));
|
||||
|
|
|
|||
|
|
@ -81,6 +81,13 @@ public class PaytestController extends CommonCtrl {
|
|||
String mchOrderNo = getValStringRequired("mchOrderNo");
|
||||
String wayCode = getValStringRequired("wayCode");
|
||||
|
||||
Byte divisionMode = getValByteRequired("divisionMode");
|
||||
String orderTitle = getValStringRequired("orderTitle");
|
||||
|
||||
if(StringUtils.isEmpty(orderTitle)){
|
||||
throw new BizException("订单标题不能为空");
|
||||
}
|
||||
|
||||
// 前端明确了支付参数的类型 payDataType
|
||||
String payDataType = getValString("payDataType");
|
||||
String authCode = getValString("authCode");
|
||||
|
|
@ -102,9 +109,10 @@ public class PaytestController extends CommonCtrl {
|
|||
model.setAmount(amount);
|
||||
model.setCurrency("CNY");
|
||||
model.setClientIp(getClientIp());
|
||||
model.setSubject(getCurrentMchNo() + "商户联调");
|
||||
model.setBody(getCurrentMchNo() + "商户联调");
|
||||
model.setSubject(orderTitle + "[" + getCurrentMchNo() + "商户联调]");
|
||||
model.setBody(orderTitle + "[" + getCurrentMchNo() + "商户联调]");
|
||||
model.setNotifyUrl(sysConfigService.getDBApplicationConfig().getMchSiteUrl() + "/api/anon/paytestNotify/payOrder"); //回调地址
|
||||
model.setDivisionMode(divisionMode); //分账模式
|
||||
|
||||
//设置扩展参数
|
||||
JSONObject extParams = new JSONObject();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.jeequan.jeepay.pay.channel;
|
||||
|
||||
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.pay.util.ChannelCertConfigKitBean;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -32,6 +33,15 @@ public abstract class AbstractPaymentService implements IPaymentService{
|
|||
@Autowired protected SysConfigService sysConfigService;
|
||||
@Autowired protected ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
|
||||
/** 订单分账(一般用作 如微信订单将在下单处做标记) */
|
||||
protected boolean isDivisionOrder(PayOrder payOrder){
|
||||
//订单分账, 将冻结商户资金。
|
||||
if(payOrder.getDivisionMode() != null && (PayOrder.DIVISION_MODE_AUTO == payOrder.getDivisionMode() || PayOrder.DIVISION_MODE_MANUAL == payOrder.getDivisionMode() )){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(){
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/pay/notify/" + getIfCode();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.jeequan.jeepay.pay.channel;
|
||||
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
||||
import com.jeequan.jeepay.core.entity.TransferOrder;
|
||||
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
|
||||
|
|
@ -40,9 +41,9 @@ public interface IDivisionService {
|
|||
boolean isSupport();
|
||||
|
||||
/** 绑定关系 **/
|
||||
boolean bind(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext);
|
||||
ChannelRetMsg bind(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext);
|
||||
|
||||
/** 单次分账 (无需调用完结接口,或自动解冻商户资金) **/
|
||||
boolean singleDivision(List<PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext);
|
||||
ChannelRetMsg singleDivision(PayOrder payOrder, List<PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeequan.jeepay.pay.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alipay.api.domain.*;
|
||||
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
|
||||
import com.alipay.api.request.AlipayTradeRoyaltyRelationBindRequest;
|
||||
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
|
||||
import com.alipay.api.response.AlipayTradeRoyaltyRelationBindResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.RegKit;
|
||||
import com.jeequan.jeepay.core.utils.SeqKit;
|
||||
import com.jeequan.jeepay.pay.channel.IDivisionService;
|
||||
import com.jeequan.jeepay.pay.exception.ChannelException;
|
||||
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账接口: 支付宝官方
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/8/22 09:05
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayDivisionService implements IDivisionService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg bind(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
|
||||
try {
|
||||
AlipayTradeRoyaltyRelationBindRequest request = new AlipayTradeRoyaltyRelationBindRequest();
|
||||
AlipayTradeRoyaltyRelationBindModel model = new AlipayTradeRoyaltyRelationBindModel();
|
||||
request.setBizModel(model);
|
||||
model.setOutRequestNo(SeqKit.genDivisionBatchId());
|
||||
|
||||
RoyaltyEntity royaltyEntity = new RoyaltyEntity();
|
||||
|
||||
royaltyEntity.setType("loginName");
|
||||
if(RegKit.isAlipayUserId(mchDivisionReceiver.getAccNo())){
|
||||
royaltyEntity.setType("userId");
|
||||
}
|
||||
royaltyEntity.setAccount(mchDivisionReceiver.getAccNo());
|
||||
royaltyEntity.setName(mchDivisionReceiver.getAccName());
|
||||
royaltyEntity.setMemo(mchDivisionReceiver.getRelationTypeName()); //分账关系描述
|
||||
model.setReceiverList(Arrays.asList(royaltyEntity));
|
||||
|
||||
AlipayTradeRoyaltyRelationBindResponse alipayResp = mchAppConfigContext.getAlipayClientWrapper().execute(request);
|
||||
|
||||
if(alipayResp.isSuccess()){
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
//异常:
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (ChannelException e) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(e.getChannelRetMsg().getChannelErrCode());
|
||||
channelRetMsg.setChannelErrMsg(e.getChannelRetMsg().getChannelErrMsg());
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("绑定支付宝账号异常", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg singleDivision(PayOrder payOrder, List<PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
|
||||
try {
|
||||
|
||||
AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
|
||||
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
|
||||
request.setBizModel(model);
|
||||
|
||||
model.setOutRequestNo(recordList.get(0).getBatchOrderId()); //结算请求流水号,由商家自定义。32个字符以内,仅可包含字母、数字、下划线。需保证在商户端不重复。
|
||||
model.setTradeNo(recordList.get(0).getPayOrderChannelOrderNo()); //支付宝订单号
|
||||
|
||||
List<OpenApiRoyaltyDetailInfoPojo> reqReceiverList = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < recordList.size(); i++) {
|
||||
|
||||
PayOrderDivisionRecord record = recordList.get(i);
|
||||
|
||||
if(record.getCalDivisionAmount() <= 0){ //金额为 0 不参与分账处理
|
||||
continue;
|
||||
}
|
||||
|
||||
OpenApiRoyaltyDetailInfoPojo reqReceiver = new OpenApiRoyaltyDetailInfoPojo();
|
||||
reqReceiver.setRoyaltyType("transfer"); //分账类型: 普通分账
|
||||
|
||||
// 出款信息
|
||||
// reqReceiver.setTransOutType("loginName"); reqReceiver.setTransOut("xqxemt4735@sandbox.com");
|
||||
|
||||
// 入款信息
|
||||
reqReceiver.setTransIn(record.getAccNo()); //收入方账号
|
||||
reqReceiver.setTransInType("loginName");
|
||||
if(RegKit.isAlipayUserId(record.getAccNo())){
|
||||
reqReceiver.setTransInType("userId");
|
||||
}
|
||||
// 分账金额
|
||||
reqReceiver.setAmount(AmountUtil.convertCent2Dollar(record.getCalDivisionAmount()));
|
||||
reqReceiver.setDesc("[" + payOrder.getPayOrderId() + "]订单分账");
|
||||
reqReceiverList.add(reqReceiver);
|
||||
|
||||
}
|
||||
|
||||
if(reqReceiverList.isEmpty()){ // 当无分账用户时, 支付宝不允许发起分账请求, 支付宝没有完结解决,直接响应成功即可。
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
model.setRoyaltyParameters(reqReceiverList); // 分账明细信息
|
||||
|
||||
// 完结
|
||||
SettleExtendParams settleExtendParams = new SettleExtendParams();
|
||||
settleExtendParams.setRoyaltyFinish("true");
|
||||
model.setExtendParams(settleExtendParams);
|
||||
|
||||
//调起支付宝分账接口
|
||||
if(log.isInfoEnabled()){
|
||||
log.info("订单:[{}], 支付宝分账请求:{}", payOrder.getPayOrderId(), JSON.toJSONString(model));
|
||||
}
|
||||
AlipayTradeOrderSettleResponse alipayResp = mchAppConfigContext.getAlipayClientWrapper().execute(request);
|
||||
log.info("订单:[{}], 支付宝分账响应:{}", payOrder.getPayOrderId(), alipayResp.getBody());
|
||||
if(alipayResp.isSuccess()){
|
||||
return ChannelRetMsg.confirmSuccess(alipayResp.getTradeNo());
|
||||
}
|
||||
|
||||
//异常:
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (ChannelException e) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(e.getChannelRetMsg().getChannelErrCode());
|
||||
channelRetMsg.setChannelErrMsg(e.getChannelRetMsg().getChannelErrMsg());
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("绑定支付宝账号异常", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ public class AlipayBizController extends AbstractCtrl {
|
|||
}
|
||||
|
||||
String redirectUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/channelbiz/alipay/appToAppAuthCallback";
|
||||
response.sendRedirect(String.format(oauthUrl, alipayIsvParams.getAppId(), URLUtil.encode(redirectUrl), isvAndMchAppId));
|
||||
response.sendRedirect(String.format(oauthUrl, alipayIsvParams.getAppId(), URLUtil.encodeAll(redirectUrl), isvAndMchAppId));
|
||||
}
|
||||
|
||||
/** 支付宝授权回调地址 **/
|
||||
|
|
|
|||
|
|
@ -17,19 +17,21 @@ package com.jeequan.jeepay.pay.channel.wxpay;
|
|||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingReceiverRequest;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingReceiverResult;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingRequest;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingResult;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.*;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
||||
import com.jeequan.jeepay.core.utils.SeqKit;
|
||||
import com.jeequan.jeepay.pay.channel.IDivisionService;
|
||||
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
|
||||
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -54,12 +56,15 @@ public class WxpayDivisionService implements IDivisionService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean bind(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
public ChannelRetMsg bind(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
try {
|
||||
|
||||
ProfitSharingReceiverRequest request = new ProfitSharingReceiverRequest();
|
||||
|
||||
//放置isv信息
|
||||
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
|
||||
|
||||
JSONObject receiverJSON = new JSONObject();
|
||||
|
||||
// 0-个人, 1-商户 (目前仅支持服务商appI获取个人openId, 即: PERSONAL_OPENID, 不支持 PERSONAL_SUB_OPENID )
|
||||
|
|
@ -73,30 +78,49 @@ public class WxpayDivisionService implements IDivisionService {
|
|||
ProfitSharingReceiverResult profitSharingReceiverResult =
|
||||
mchAppConfigContext.getWxServiceWrapper().getWxPayService().getProfitSharingService().addReceiver(request);
|
||||
|
||||
// 明确成功
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
|
||||
} catch (WxPayException wxPayException) {
|
||||
wxPayException.printStackTrace();
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
WxpayKit.commonSetErrInfo(channelRetMsg, wxPayException);
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
log.error("请求微信绑定分账接口异常!", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg("系统异常:" + e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean singleDivision(List<PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext) {
|
||||
public ChannelRetMsg singleDivision(PayOrder payOrder, List<PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
try {
|
||||
|
||||
if(true || recordList.isEmpty()){
|
||||
return true;
|
||||
}
|
||||
|
||||
ProfitSharingRequest request = new ProfitSharingRequest();
|
||||
request.setTransactionId(recordList.get(0).getPayOrderChannelOrderNo());
|
||||
request.setOutOrderNo(recordList.get(0).getBatchOrderId());
|
||||
request.setTransactionId(payOrder.getChannelOrderNo());
|
||||
|
||||
//放置isv信息
|
||||
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
|
||||
|
||||
if(recordList.isEmpty()){
|
||||
request.setOutOrderNo(SeqKit.genDivisionBatchId()); // 随机生成一个订单号
|
||||
}else{
|
||||
request.setOutOrderNo(recordList.get(0).getBatchOrderId()); //取到批次号
|
||||
}
|
||||
|
||||
JSONArray receiverJSONArray = new JSONArray();
|
||||
|
||||
for (PayOrderDivisionRecord record : recordList) {
|
||||
for (int i = 0; i < recordList.size(); i++) {
|
||||
|
||||
PayOrderDivisionRecord record = recordList.get(i);
|
||||
if(record.getCalDivisionAmount() <= 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject receiverJSON = new JSONObject();
|
||||
// 0-个人, 1-商户 (目前仅支持服务商appI获取个人openId, 即: PERSONAL_OPENID, 不支持 PERSONAL_SUB_OPENID )
|
||||
receiverJSON.put("type", record.getAccType() == 0 ? "PERSONAL_OPENID" : "MERCHANT_ID");
|
||||
|
|
@ -106,15 +130,45 @@ public class WxpayDivisionService implements IDivisionService {
|
|||
receiverJSONArray.add(receiverJSON);
|
||||
}
|
||||
|
||||
//不存在接收账号时,订单完结(解除冻结金额)
|
||||
if(receiverJSONArray.isEmpty()){
|
||||
return ChannelRetMsg.confirmSuccess(this.divisionFinish(payOrder, mchAppConfigContext));
|
||||
}
|
||||
|
||||
request.setReceivers(receiverJSONArray.toJSONString());
|
||||
|
||||
ProfitSharingResult profitSharingResult = mchAppConfigContext.getWxServiceWrapper().getWxPayService().getProfitSharingService().profitSharing(request);
|
||||
return ChannelRetMsg.confirmSuccess(profitSharingResult.getOrderId());
|
||||
|
||||
} catch (WxPayException wxPayException) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
WxpayKit.commonSetErrInfo(channelRetMsg, wxPayException);
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("微信分账失败", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** 调用订单的完结接口 (分账对象不存在时) */
|
||||
private String divisionFinish(PayOrder payOrder,MchAppConfigContext mchAppConfigContext) throws WxPayException {
|
||||
|
||||
ProfitSharingFinishRequest request = new ProfitSharingFinishRequest();
|
||||
|
||||
//放置isv信息
|
||||
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
|
||||
|
||||
request.setSubAppId(null); // 传入subAppId 将导致签名失败
|
||||
|
||||
request.setTransactionId(payOrder.getChannelOrderNo());
|
||||
request.setOutOrderNo(SeqKit.genDivisionBatchId());
|
||||
request.setDescription("完结分账");
|
||||
return mchAppConfigContext.getWxServiceWrapper().getWxPayService().getProfitSharingService().profitSharingFinish(request).getOrderId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@ public class WxpayPaymentService extends AbstractPaymentService {
|
|||
request.setNotifyUrl(getNotifyUrl());
|
||||
request.setProductId(System.currentTimeMillis()+"");
|
||||
|
||||
//订单分账, 将冻结商户资金。
|
||||
if(isDivisionOrder(payOrder)){
|
||||
request.setProfitSharing("Y");
|
||||
}
|
||||
|
||||
// 特约商户
|
||||
if(mchAppConfigContext.isIsvsubMch()){
|
||||
WxpayIsvsubMchParams isvsubMchParams = mchAppConfigContext.getIsvsubMchParamsByIfCode(getIfCode(), WxpayIsvsubMchParams.class);
|
||||
|
|
@ -125,6 +130,13 @@ public class WxpayPaymentService extends AbstractPaymentService {
|
|||
sceneInfo.put("payer_client_ip", payOrder.getClientIp());
|
||||
reqJSON.put("scene_info", sceneInfo);
|
||||
|
||||
//订单分账, 将冻结商户资金。
|
||||
if(isDivisionOrder(payOrder)){
|
||||
JSONObject settleInfo = new JSONObject();
|
||||
settleInfo.put("profit_sharing", true);
|
||||
reqJSON.put("settle_info", settleInfo);
|
||||
}
|
||||
|
||||
WxPayService wxPayService = mchAppConfigContext.getWxServiceWrapper().getWxPayService();
|
||||
if(mchAppConfigContext.isIsvsubMch()){ // 特约商户
|
||||
WxpayIsvsubMchParams isvsubMchParams = mchAppConfigContext.getIsvsubMchParamsByIfCode(getIfCode(), WxpayIsvsubMchParams.class);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,11 @@ public class WxBar extends WxpayPaymentService {
|
|||
request.setSpbillCreateIp(payOrder.getClientIp());
|
||||
request.setAuthCode(bizRQ.getAuthCode().trim());
|
||||
|
||||
//订单分账, 将冻结商户资金。
|
||||
if(isDivisionOrder(payOrder)){
|
||||
request.setProfitSharing("Y");
|
||||
}
|
||||
|
||||
//放置isv信息
|
||||
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeequan.jeepay.pay.ctrl.division;
|
||||
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiverGroup;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.ApiRes;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.pay.channel.IDivisionService;
|
||||
import com.jeequan.jeepay.pay.ctrl.ApiController;
|
||||
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.pay.rqrs.division.DivisionReceiverBindRQ;
|
||||
import com.jeequan.jeepay.pay.rqrs.division.DivisionReceiverBindRS;
|
||||
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.pay.rqrs.transfer.TransferOrderRS;
|
||||
import com.jeequan.jeepay.pay.service.ConfigContextService;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverGroupService;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverService;
|
||||
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 分账账号绑定
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/8/25 9:07
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class MchDivisionReceiverBindController extends ApiController {
|
||||
|
||||
@Autowired private ConfigContextService configContextService;
|
||||
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
|
||||
@Autowired private MchDivisionReceiverService mchDivisionReceiverService;
|
||||
@Autowired private MchDivisionReceiverGroupService mchDivisionReceiverGroupService;
|
||||
|
||||
/** 分账账号绑定 **/
|
||||
@PostMapping("/api/division/receiver/bind")
|
||||
public ApiRes bind(){
|
||||
|
||||
//获取参数 & 验签
|
||||
DivisionReceiverBindRQ bizRQ = getRQByWithMchSign(DivisionReceiverBindRQ.class);
|
||||
|
||||
try {
|
||||
|
||||
//检查商户应用是否存在该接口
|
||||
String ifCode = bizRQ.getIfCode();
|
||||
|
||||
|
||||
// 商户配置信息
|
||||
MchAppConfigContext mchAppConfigContext = configContextService.getMchAppConfigContext(bizRQ.getMchNo(), bizRQ.getAppId());
|
||||
if(mchAppConfigContext == null){
|
||||
throw new BizException("获取商户应用信息失败");
|
||||
}
|
||||
|
||||
MchInfo mchInfo = mchAppConfigContext.getMchInfo();
|
||||
|
||||
if(!payInterfaceConfigService.mchAppHasAvailableIfCode(bizRQ.getAppId(), ifCode)){
|
||||
throw new BizException("商户应用的支付配置不存在或已关闭");
|
||||
}
|
||||
|
||||
MchDivisionReceiverGroup group = mchDivisionReceiverGroupService.findByIdAndMchNo(bizRQ.getReceiverGroupId(), bizRQ.getMchNo());
|
||||
if(group == null){
|
||||
throw new BizException("商户分账账号组不存在,请检查或进入商户平台进行创建操作");
|
||||
}
|
||||
|
||||
BigDecimal divisionProfit = new BigDecimal(bizRQ.getDivisionProfit());
|
||||
if(divisionProfit.compareTo(BigDecimal.ZERO) <= 0 || divisionProfit.compareTo(BigDecimal.ONE) > 1){
|
||||
throw new BizException("账号分账比例有误, 配置值为[0.0001~1.0000]");
|
||||
}
|
||||
|
||||
|
||||
//生成数据库对象信息 (数据不完成, 暂时不可入库操作)
|
||||
MchDivisionReceiver receiver = genRecord(bizRQ, group, mchInfo, divisionProfit);
|
||||
|
||||
//调起上游接口
|
||||
|
||||
IDivisionService divisionService = SpringBeansUtil.getBean(ifCode + "DivisionService", IDivisionService.class);
|
||||
if(divisionService == null){
|
||||
throw new BizException("系统不支持该分账接口");
|
||||
}
|
||||
|
||||
|
||||
ChannelRetMsg retMsg = divisionService.bind(receiver, mchAppConfigContext);
|
||||
if(retMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS){
|
||||
|
||||
receiver.setState(CS.YES);
|
||||
receiver.setBindSuccessTime(new Date());
|
||||
mchDivisionReceiverService.save(receiver);
|
||||
|
||||
}else{
|
||||
|
||||
receiver.setState(CS.NO);
|
||||
receiver.setChannelBindResult(retMsg.getChannelErrMsg());
|
||||
}
|
||||
|
||||
DivisionReceiverBindRS bizRes = DivisionReceiverBindRS.buildByRecord(receiver);
|
||||
|
||||
if(retMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS){
|
||||
|
||||
bizRes.setBindState(CS.YES);
|
||||
|
||||
}else{
|
||||
bizRes.setBindState(CS.NO);
|
||||
bizRes.setErrCode(retMsg.getChannelErrCode());
|
||||
bizRes.setErrMsg(retMsg.getChannelErrMsg());
|
||||
}
|
||||
|
||||
return ApiRes.okWithSign(bizRes, mchAppConfigContext.getMchApp().getAppSecret());
|
||||
|
||||
} catch (BizException e) {
|
||||
return ApiRes.customFail(e.getMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("系统异常:{}", e);
|
||||
return ApiRes.customFail("系统异常");
|
||||
}
|
||||
}
|
||||
|
||||
private MchDivisionReceiver genRecord(DivisionReceiverBindRQ bizRQ, MchDivisionReceiverGroup group, MchInfo mchInfo, BigDecimal divisionProfit){
|
||||
|
||||
MchDivisionReceiver receiver = new MchDivisionReceiver();
|
||||
receiver.setReceiverAlias(StringUtils.defaultIfEmpty(bizRQ.getReceiverAlias(), bizRQ.getAccNo())); //别名
|
||||
receiver.setReceiverGroupId(bizRQ.getReceiverGroupId()); //分组ID
|
||||
receiver.setReceiverGroupName(group.getReceiverGroupName()); //组名称
|
||||
receiver.setMchNo(bizRQ.getMchNo()); //商户号
|
||||
receiver.setIsvNo(mchInfo.getIsvNo()); //isvNo
|
||||
receiver.setAppId(bizRQ.getAppId()); //appId
|
||||
receiver.setIfCode(bizRQ.getIfCode()); //接口代码
|
||||
receiver.setAccType(bizRQ.getAccType()); //账号类型
|
||||
receiver.setAccNo(bizRQ.getAccNo()); //账号
|
||||
receiver.setAccName(bizRQ.getAccName()); //账号名称
|
||||
receiver.setRelationType(bizRQ.getRelationType()); //关系
|
||||
|
||||
receiver.setRelationTypeName(getRelationTypeName(bizRQ.getRelationType())); //关系名称
|
||||
|
||||
if(receiver.getRelationTypeName() == null){
|
||||
receiver.setRelationTypeName(bizRQ.getRelationTypeName());
|
||||
}
|
||||
|
||||
receiver.setDivisionProfit(divisionProfit); //分账比例
|
||||
receiver.setChannelExtInfo(bizRQ.getChannelExtInfo()); //渠道信息
|
||||
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public String getRelationTypeName(String relationType){
|
||||
|
||||
if("PARTNER".equals(relationType)){
|
||||
return "合作伙伴";
|
||||
}else if("SERVICE_PROVIDER".equals(relationType)){
|
||||
return "服务商";
|
||||
}else if("STORE".equals(relationType)){
|
||||
return "门店";
|
||||
}else if("STAFF".equals(relationType)){
|
||||
return "员工";
|
||||
}else if("STORE_OWNER".equals(relationType)){
|
||||
return "店主";
|
||||
}else if("HEADQUARTER".equals(relationType)){
|
||||
return "总部";
|
||||
}else if("BRAND".equals(relationType)){
|
||||
return "品牌方";
|
||||
}else if("DISTRIBUTOR".equals(relationType)){
|
||||
return "分销商";
|
||||
}else if("USER".equals(relationType)){
|
||||
return "用户";
|
||||
}else if("SUPPLIER".equals(relationType)){
|
||||
return "供应商";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -234,7 +234,6 @@ public abstract class AbstractPayOrderController extends ApiController {
|
|||
}
|
||||
|
||||
payOrder.setMchFeeAmount(AmountUtil.calPercentageFee(payOrder.getAmount(), payOrder.getMchFeeRate())); //商户手续费,单位分
|
||||
payOrder.setMchIncomeAmount(payOrder.getAmount() - payOrder.getMchFeeAmount()); //商户入账金额(支付金额-手续费),单位分
|
||||
|
||||
payOrder.setCurrency(rq.getCurrency()); //币种
|
||||
payOrder.setState(PayOrder.STATE_INIT); //订单状态, 默认订单生成状态
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.utils.JeepayKit;
|
||||
import com.jeequan.jeepay.core.utils.JsonKit;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.core.utils.StringKit;
|
||||
import com.jeequan.jeepay.pay.channel.IChannelUserService;
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ public class AlipayClientWrapper {
|
|||
alipayResp = alipayClient.execute(request);
|
||||
}
|
||||
|
||||
//判断返回的值: // TODO
|
||||
|
||||
return alipayResp;
|
||||
|
||||
} catch (AlipayApiException e) { // 调起接口前出现异常,如私钥问题。 调起后出现验签异常等。
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|||
import com.jeequan.jeepay.components.mq.model.PayOrderDivisionMQ;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiverGroup;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
|
|
@ -31,7 +32,9 @@ import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
|||
import com.jeequan.jeepay.pay.channel.IDivisionService;
|
||||
import com.jeequan.jeepay.pay.channel.ITransferService;
|
||||
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.pay.service.ConfigContextService;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverGroupService;
|
||||
import com.jeequan.jeepay.service.impl.MchDivisionReceiverService;
|
||||
import com.jeequan.jeepay.service.impl.PayOrderDivisionRecordService;
|
||||
import com.jeequan.jeepay.service.impl.PayOrderService;
|
||||
|
|
@ -41,6 +44,7 @@ import org.springframework.stereotype.Component;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -59,6 +63,8 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
@Autowired
|
||||
private MchDivisionReceiverService mchDivisionReceiverService;
|
||||
@Autowired
|
||||
private MchDivisionReceiverGroupService mchDivisionReceiverGroupService;
|
||||
@Autowired
|
||||
private PayOrderDivisionRecordService payOrderDivisionRecordService;
|
||||
@Autowired
|
||||
private ConfigContextService configContextService;
|
||||
|
|
@ -95,8 +101,8 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
return ;
|
||||
}
|
||||
|
||||
// 查询所有的分账接收对象
|
||||
List<MchDivisionReceiver> allReceiver = queryReceiver(payOrder, payload.getReceiverList());
|
||||
// 查询&过滤 所有的分账接收对象
|
||||
List<MchDivisionReceiver> allReceiver = this.queryReceiver(payOrder, payload.getReceiverList());
|
||||
|
||||
//得到全部分账比例 (所有待分账账号的分账比例总和)
|
||||
BigDecimal allDivisionProfit = BigDecimal.ZERO;
|
||||
|
|
@ -104,8 +110,11 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
allDivisionProfit = allDivisionProfit.add(receiver.getDivisionProfit());
|
||||
}
|
||||
|
||||
//剩余待分账金额 (用作最后一个分账账号的 计算, 避免出现分账金额超出最大)
|
||||
Long subDivisionAmount = AmountUtil.calPercentageFee(payOrder.getMchIncomeAmount(), allDivisionProfit);
|
||||
//计算分账金额 = 商家实际入账金额
|
||||
Long payOrderDivisionAmount = payOrderService.calMchIncomeAmount(payOrder);
|
||||
|
||||
//剩余待分账金额 (用作最后一个分账账号的 计算, 避免出现分账金额超出最大) [结果向下取整 , 避免出现金额溢出的情况。 ]
|
||||
Long subDivisionAmount = AmountUtil.calPercentageFee(payOrderDivisionAmount, allDivisionProfit, BigDecimal.ROUND_FLOOR);
|
||||
|
||||
List<PayOrderDivisionRecord> recordList = new ArrayList<>();
|
||||
|
||||
|
|
@ -115,7 +124,7 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
|
||||
for (MchDivisionReceiver receiver : allReceiver) {
|
||||
|
||||
PayOrderDivisionRecord record = genRecord(batchOrderId, payOrder, receiver, subDivisionAmount);
|
||||
PayOrderDivisionRecord record = genRecord(batchOrderId, payOrder, receiver, payOrderDivisionAmount, subDivisionAmount);
|
||||
|
||||
//剩余金额
|
||||
subDivisionAmount = subDivisionAmount - record.getCalDivisionAmount();
|
||||
|
|
@ -134,14 +143,19 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
throw new BizException("通道无此分账接口");
|
||||
}
|
||||
|
||||
divisionService.singleDivision(recordList, configContextService.getMchAppConfigContext(payOrder.getMchNo(), payOrder.getAppId()));
|
||||
ChannelRetMsg channelRetMsg = divisionService.singleDivision(payOrder, recordList, configContextService.getMchAppConfigContext(payOrder.getMchNo(), payOrder.getAppId()));
|
||||
|
||||
if(true) {
|
||||
// 确认分账成功
|
||||
if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS) {
|
||||
|
||||
//分账成功
|
||||
payOrderDivisionRecordService.updateRecordSuccessOrFail(recordList, PayOrderDivisionRecord.STATE_SUCCESS,
|
||||
channelRetMsg.getChannelOrderId(), channelRetMsg.getChannelOriginResponse());
|
||||
|
||||
}else{
|
||||
//分账失败
|
||||
payOrderDivisionRecordService.updateRecordSuccessOrFail(recordList, PayOrderDivisionRecord.STATE_FAIL,
|
||||
channelRetMsg.getChannelOrderId(), channelRetMsg.getChannelErrMsg());
|
||||
}
|
||||
|
||||
} catch (BizException e) {
|
||||
|
|
@ -149,14 +163,14 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
|
||||
} catch (Exception e) {
|
||||
log.error("{}, 调用分账接口异常", logPrefix, e);
|
||||
|
||||
//分账失败
|
||||
|
||||
payOrderDivisionRecordService.updateRecordSuccessOrFail(recordList, PayOrderDivisionRecord.STATE_FAIL,
|
||||
null, "系统异常:" + e.getMessage());
|
||||
}
|
||||
|
||||
//更新 支付订单主表状态 分账任务已结束。
|
||||
payOrderService.update(new LambdaUpdateWrapper<PayOrder>()
|
||||
.set(PayOrder::getDivisionState, PayOrder.DIVISION_STATE_FINISH)
|
||||
.set(PayOrder::getDivisionLastTime, new Date())
|
||||
.eq(PayOrder::getPayOrderId, payload.getPayOrderId())
|
||||
.eq(PayOrder::getDivisionState, PayOrder.DIVISION_STATE_ING)
|
||||
);
|
||||
|
|
@ -168,7 +182,8 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
|
||||
|
||||
/** 生成对象信息 **/
|
||||
private PayOrderDivisionRecord genRecord(String batchOrderId, PayOrder payOrder, MchDivisionReceiver receiver, Long subDivisionAmount){
|
||||
private PayOrderDivisionRecord genRecord(String batchOrderId, PayOrder payOrder, MchDivisionReceiver receiver,
|
||||
Long payOrderDivisionAmount, Long subDivisionAmount){
|
||||
|
||||
PayOrderDivisionRecord record = new PayOrderDivisionRecord();
|
||||
record.setMchNo(payOrder.getMchNo());
|
||||
|
|
@ -180,11 +195,12 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
record.setPayOrderId(payOrder.getPayOrderId());
|
||||
record.setPayOrderChannelOrderNo(payOrder.getChannelOrderNo()); //支付订单渠道订单号
|
||||
record.setPayOrderAmount(payOrder.getAmount()); //订单金额
|
||||
record.setPayOrderDivisionAmount(payOrder.getMchIncomeAmount()); // 订单实际分账金额, 单位:分(订单金额 - 商户手续费 - 已退款金额) //TODO 实际计算金额
|
||||
record.setPayOrderDivisionAmount(payOrderDivisionAmount); // 订单计算分账金额
|
||||
record.setBatchOrderId(batchOrderId); //系统分账批次号
|
||||
record.setState(MchDivisionReceiver.STATE_WAIT); //状态: 待分账
|
||||
record.setState(PayOrderDivisionRecord.STATE_WAIT); //状态: 待分账
|
||||
record.setReceiverId(receiver.getReceiverId());
|
||||
record.setReceiverGroupId(receiver.getReceiverGroupId());
|
||||
record.setReceiverAlias(receiver.getReceiverAlias());
|
||||
record.setAccType(receiver.getAccType());
|
||||
record.setAccNo(receiver.getAccNo());
|
||||
record.setAccName(receiver.getAccName());
|
||||
|
|
@ -195,7 +211,12 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
if( subDivisionAmount <= 0 ) {
|
||||
record.setCalDivisionAmount(0L);
|
||||
}else{
|
||||
|
||||
//计算的分账金额
|
||||
record.setCalDivisionAmount(AmountUtil.calPercentageFee(record.getPayOrderDivisionAmount(), record.getDivisionProfit()));
|
||||
if(record.getCalDivisionAmount() > subDivisionAmount){ // 分账金额超过剩余总金额时: 将按照剩余金额进行分账。
|
||||
record.setCalDivisionAmount(subDivisionAmount);
|
||||
}
|
||||
}
|
||||
|
||||
return record;
|
||||
|
|
@ -212,6 +233,20 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
queryWrapper.eq(MchDivisionReceiver::getIfCode, payOrder.getIfCode()); //ifCode
|
||||
queryWrapper.eq(MchDivisionReceiver::getState, CS.PUB_USABLE); // 可用状态的账号
|
||||
|
||||
// 未设置接收者账号信息, 需要查询 自动分账组的账号
|
||||
if(customerDivisionReceiverList == null){
|
||||
|
||||
List<MchDivisionReceiverGroup> groups = mchDivisionReceiverGroupService.list(
|
||||
MchDivisionReceiverGroup.gw().eq(MchDivisionReceiverGroup::getMchNo, payOrder.getMchNo())
|
||||
.eq(MchDivisionReceiverGroup::getAutoDivisionFlag, CS.YES));
|
||||
|
||||
if(groups.isEmpty()){
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
queryWrapper.eq(MchDivisionReceiver::getReceiverGroupId, groups.get(0).getReceiverGroupId());
|
||||
}
|
||||
|
||||
//全部分账账号
|
||||
List<MchDivisionReceiver> allMchReceiver = mchDivisionReceiverService.list(queryWrapper);
|
||||
if(allMchReceiver.isEmpty()){
|
||||
|
|
@ -228,7 +263,6 @@ public class PayOrderDivisionMQReceiver implements PayOrderDivisionMQ.IMQReceive
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
// 过滤账号
|
||||
List<MchDivisionReceiver> filterMchReceiver = new ArrayList<>();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeequan.jeepay.pay.rqrs.division;
|
||||
|
||||
import com.jeequan.jeepay.pay.rqrs.AbstractMchAppRQ;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/*
|
||||
* 分账账号的绑定 请求参数
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeequan.com
|
||||
* @date 2021/8/25 09:21
|
||||
*/
|
||||
@Data
|
||||
public class DivisionReceiverBindRQ extends AbstractMchAppRQ {
|
||||
|
||||
/** 支付接口代码 **/
|
||||
@NotBlank(message="支付接口代码不能为空")
|
||||
private String ifCode;
|
||||
|
||||
/** 接收者账号别名 **/
|
||||
private String receiverAlias;
|
||||
|
||||
/** 组ID **/
|
||||
@NotNull(message="组ID不能为空, 若不存在请先登录商户平台进行创建操作")
|
||||
private Long receiverGroupId;
|
||||
|
||||
/** 分账接收账号类型: 0-个人(对私) 1-商户(对公) **/
|
||||
@NotNull(message="分账接收账号类型不能为空")
|
||||
@Range(min = 0, max = 1, message = "分账接收账号类型设置有误")
|
||||
private Byte accType;
|
||||
|
||||
/** 分账接收账号 **/
|
||||
@NotBlank(message="分账接收账号不能为空")
|
||||
private String accNo;
|
||||
|
||||
/** 分账接收账号名称 **/
|
||||
private String accName;
|
||||
|
||||
/** 分账关系类型(参考微信), 如: SERVICE_PROVIDER 服务商等 **/
|
||||
@NotBlank(message="分账关系类型不能为空")
|
||||
private String relationType;
|
||||
|
||||
/** 当选择自定义时,需要录入该字段。 否则为对应的名称 **/
|
||||
private String relationTypeName;
|
||||
|
||||
/** 渠道特殊信息 */
|
||||
private String channelExtInfo;
|
||||
|
||||
/** 分账比例 **/
|
||||
@NotBlank(message="分账比例不能为空")
|
||||
private String divisionProfit;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeequan.jeepay.pay.rqrs.division;
|
||||
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
|
||||
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/*
|
||||
* 绑定账户 响应参数
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeequan.com
|
||||
* @date 2021/6/8 17:34
|
||||
*/
|
||||
@Data
|
||||
public class DivisionReceiverBindRS extends AbstractRS {
|
||||
|
||||
|
||||
/**
|
||||
* 分账接收者ID
|
||||
*/
|
||||
private Long receiverId;
|
||||
|
||||
/**
|
||||
* 接收者账号别名
|
||||
*/
|
||||
private String receiverAlias;
|
||||
|
||||
/**
|
||||
* 组ID(便于商户接口使用)
|
||||
*/
|
||||
private Long receiverGroupId;
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
private String mchNo;
|
||||
|
||||
/**
|
||||
* 应用ID
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 支付接口代码
|
||||
*/
|
||||
private String ifCode;
|
||||
|
||||
/**
|
||||
* 分账接收账号类型: 0-个人(对私) 1-商户(对公)
|
||||
*/
|
||||
private Byte accType;
|
||||
|
||||
/**
|
||||
* 分账接收账号
|
||||
*/
|
||||
private String accNo;
|
||||
|
||||
/**
|
||||
* 分账接收账号名称
|
||||
*/
|
||||
private String accName;
|
||||
|
||||
/**
|
||||
* 分账关系类型(参考微信), 如: SERVICE_PROVIDER 服务商等
|
||||
*/
|
||||
private String relationType;
|
||||
|
||||
/**
|
||||
* 当选择自定义时,需要录入该字段。 否则为对应的名称
|
||||
*/
|
||||
private String relationTypeName;
|
||||
|
||||
|
||||
/**
|
||||
* 渠道特殊信息
|
||||
*/
|
||||
private String channelExtInfo;
|
||||
|
||||
/**
|
||||
* 绑定成功时间
|
||||
*/
|
||||
private Long bindSuccessTime;
|
||||
|
||||
/**
|
||||
* 分账比例
|
||||
*/
|
||||
private BigDecimal divisionProfit;
|
||||
|
||||
/**
|
||||
* 分账状态 1-绑定成功, 0-绑定异常
|
||||
*/
|
||||
private Byte bindState;
|
||||
|
||||
/**
|
||||
* 支付渠道错误码
|
||||
*/
|
||||
private String errCode;
|
||||
|
||||
/**
|
||||
* 支付渠道错误信息
|
||||
*/
|
||||
private String errMsg;
|
||||
|
||||
|
||||
|
||||
public static DivisionReceiverBindRS buildByRecord(MchDivisionReceiver record){
|
||||
|
||||
if(record == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
DivisionReceiverBindRS result = new DivisionReceiverBindRS();
|
||||
BeanUtils.copyProperties(record, result);
|
||||
result.setBindSuccessTime(record.getBindSuccessTime() != null ? record.getBindSuccessTime().getTime() : null);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -50,6 +50,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
@ -181,6 +182,12 @@ public class ConfigContextService {
|
|||
return ;
|
||||
}
|
||||
|
||||
|
||||
// 商户应用mchNo 与参数不匹配
|
||||
if(!dbMchApp.getMchNo().equals(mchNo)){
|
||||
return;
|
||||
}
|
||||
|
||||
//更新商户信息主体中的商户应用
|
||||
mchInfoConfigContext.putMchApp(dbMchApp);
|
||||
|
||||
|
|
@ -256,19 +263,28 @@ public class ConfigContextService {
|
|||
/** 初始化 [ISV支付参数配置信息] **/
|
||||
public synchronized void initIsvConfigContext(String isvNo){
|
||||
|
||||
//查询出所有商户的配置信息并更新
|
||||
List<String> mchNoList = new ArrayList<>();
|
||||
mchInfoService.list(MchInfo.gw().select(MchInfo::getMchNo).eq(MchInfo::getIsvNo, isvNo)).forEach(r -> mchNoList.add(r.getMchNo()));
|
||||
|
||||
// 查询出所有 所属当前服务商的所有应用集合
|
||||
List<String> mchAppIdList = new ArrayList<>();
|
||||
if(!mchNoList.isEmpty()){
|
||||
mchAppService.list(MchApp.gw().select(MchApp::getAppId).in(MchApp::getMchNo, mchNoList)).forEach(r -> mchAppIdList.add(r.getAppId()));
|
||||
}
|
||||
|
||||
IsvConfigContext isvConfigContext = new IsvConfigContext();
|
||||
IsvInfo isvInfo = isvInfoService.getById(isvNo);
|
||||
if(isvInfo == null){
|
||||
|
||||
//查询出所有商户的配置信息并更新
|
||||
mchInfoService.list(MchInfo.gw().select(MchInfo::getMchNo).eq(MchInfo::getIsvNo, isvNo)).forEach(mchInfoItem -> {
|
||||
|
||||
for (String appId : mchAppIdList) {
|
||||
//将更新已存在缓存的商户配置信息 (每个商户下存储的为同一个 服务商配置的对象指针)
|
||||
MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(mchInfoItem.getMchNo());
|
||||
MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
|
||||
if(mchAppConfigContext != null){
|
||||
mchAppConfigContext.setIsvConfigContext(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isvConfigContextMap.remove(isvNo); // 服务商有商户不可删除, 此处不再更新商户下的配置信息
|
||||
return ;
|
||||
}
|
||||
|
|
@ -314,16 +330,13 @@ public class ConfigContextService {
|
|||
isvConfigContextMap.put(isvNo, isvConfigContext);
|
||||
|
||||
//查询出所有商户的配置信息并更新
|
||||
mchInfoService.list(MchInfo.gw().select(MchInfo::getMchNo).eq(MchInfo::getIsvNo, isvNo)).forEach(mchInfoItem -> {
|
||||
|
||||
for (String appId : mchAppIdList) {
|
||||
//将更新已存在缓存的商户配置信息 (每个商户下存储的为同一个 服务商配置的对象指针)
|
||||
MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(mchInfoItem.getMchNo());
|
||||
MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
|
||||
if(mchAppConfigContext != null){
|
||||
mchAppConfigContext.setIsvConfigContext(isvConfigContext);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public class PayOrderProcessService {
|
|||
|
||||
if(updDivisionState){
|
||||
//推送到分账MQ
|
||||
mqSender.send(PayOrderDivisionMQ.build(payOrder.getPayOrderId(), null), 1); //1分钟后执行
|
||||
mqSender.send(PayOrderDivisionMQ.build(payOrder.getPayOrderId(), null), 60); //1分钟后执行
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ public class CodeImgUtil {
|
|||
}
|
||||
|
||||
|
||||
//TODO
|
||||
// 图片宽度的一般
|
||||
private static final int IMAGE_WIDTH = 25;
|
||||
private static final int IMAGE_HEIGHT = 25;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
package com.jeequan.jeepay.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiverGroup;
|
||||
import com.jeequan.jeepay.service.mapper.MchDivisionReceiverGroupMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 分账账号组 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author [mybatis plus generator]
|
||||
* @since 2021-08-23
|
||||
*/
|
||||
@Service
|
||||
public class MchDivisionReceiverGroupService extends ServiceImpl<MchDivisionReceiverGroupMapper, MchDivisionReceiverGroup> {
|
||||
|
||||
|
||||
/** 根据ID和商户号查询 **/
|
||||
public MchDivisionReceiverGroup findByIdAndMchNo(Long groupId, String mchNo){
|
||||
return getOne(MchDivisionReceiverGroup.gw().eq(MchDivisionReceiverGroup::getReceiverGroupId, groupId).eq(MchDivisionReceiverGroup::getMchNo, mchNo));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,9 @@ import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
|||
import com.jeequan.jeepay.service.mapper.PayOrderDivisionRecordMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 分账记录表 服务实现类
|
||||
|
|
@ -16,4 +19,27 @@ import org.springframework.stereotype.Service;
|
|||
@Service
|
||||
public class PayOrderDivisionRecordService extends ServiceImpl<PayOrderDivisionRecordMapper, PayOrderDivisionRecord> {
|
||||
|
||||
|
||||
/** 更新分账记录为分账成功**/
|
||||
public void updateRecordSuccessOrFail(List<PayOrderDivisionRecord> records, Byte state, String channelBatchOrderId, String channelRespResult){
|
||||
|
||||
if(records == null || records.isEmpty()){
|
||||
return ;
|
||||
}
|
||||
|
||||
List<Long> recordIds = new ArrayList<>();
|
||||
records.stream().forEach(r -> recordIds.add(r.getRecordId()));
|
||||
|
||||
PayOrderDivisionRecord updateRecord = new PayOrderDivisionRecord();
|
||||
updateRecord.setState(state);
|
||||
updateRecord.setChannelBatchOrderId(channelBatchOrderId);
|
||||
updateRecord.setChannelRespResult(channelRespResult);
|
||||
update(updateRecord, PayOrderDivisionRecord.gw().in(PayOrderDivisionRecord::getRecordId, recordIds).eq(PayOrderDivisionRecord::getState, PayOrderDivisionRecord.STATE_WAIT));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,8 @@ import com.jeequan.jeepay.core.entity.IsvInfo;
|
|||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.PayWay;
|
||||
import com.jeequan.jeepay.service.mapper.IsvInfoMapper;
|
||||
import com.jeequan.jeepay.service.mapper.MchInfoMapper;
|
||||
import com.jeequan.jeepay.service.mapper.PayOrderMapper;
|
||||
import com.jeequan.jeepay.service.mapper.PayWayMapper;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.service.mapper.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -53,6 +51,7 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
|
|||
@Autowired private MchInfoMapper mchInfoMapper;
|
||||
@Autowired private IsvInfoMapper isvInfoMapper;
|
||||
@Autowired private PayWayMapper payWayMapper;
|
||||
@Autowired private PayOrderDivisionRecordMapper payOrderDivisionRecordMapper;
|
||||
|
||||
/** 更新订单状态 【订单生成】 --》 【支付中】 **/
|
||||
public boolean updateInit2Ing(String payOrderId, PayOrder payOrder){
|
||||
|
|
@ -65,7 +64,6 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
|
|||
updateRecord.setWayCode(payOrder.getWayCode());
|
||||
updateRecord.setMchFeeRate(payOrder.getMchFeeRate());
|
||||
updateRecord.setMchFeeAmount(payOrder.getMchFeeAmount());
|
||||
updateRecord.setMchIncomeAmount(payOrder.getMchIncomeAmount());
|
||||
|
||||
return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
|
||||
.eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_INIT));
|
||||
|
|
@ -358,4 +356,26 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
|
|||
payListMap.addAll(refundListMap);
|
||||
return payListMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算支付订单商家入账金额
|
||||
* 商家订单入账金额 (支付金额 - 手续费 - 退款金额 - 总分账金额)
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/8/26 16:39
|
||||
*/
|
||||
public Long calMchIncomeAmount(PayOrder dbPayOrder){
|
||||
|
||||
//商家订单入账金额 (支付金额 - 手续费 - 退款金额 - 总分账金额)
|
||||
Long mchIncomeAmount = dbPayOrder.getAmount() - dbPayOrder.getMchFeeAmount() - dbPayOrder.getRefundAmount();
|
||||
|
||||
//减去已分账金额
|
||||
mchIncomeAmount -= payOrderDivisionRecordMapper.sumSuccessDivisionAmount(dbPayOrder.getPayOrderId());
|
||||
|
||||
return mchIncomeAmount <= 0 ? 0 : mchIncomeAmount;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.jeequan.jeepay.service.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.jeequan.jeepay.core.entity.MchDivisionReceiverGroup;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 分账账号组 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author [mybatis plus generator]
|
||||
* @since 2021-08-23
|
||||
*/
|
||||
public interface MchDivisionReceiverGroupMapper extends BaseMapper<MchDivisionReceiverGroup> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.jeequan.jeepay.service.mapper.MchDivisionReceiverGroupMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.jeequan.jeepay.core.entity.MchDivisionReceiverGroup">
|
||||
<id column="receiver_group_id" property="receiverGroupId" />
|
||||
<result column="receiver_group_name" property="receiverGroupName" />
|
||||
<result column="mch_no" property="mchNo" />
|
||||
<result column="auto_division_flag" property="autoDivisionFlag" />
|
||||
<result column="created_uid" property="createdUid" />
|
||||
<result column="created_by" property="createdBy" />
|
||||
<result column="created_at" property="createdAt" />
|
||||
<result column="updated_at" property="updatedAt" />
|
||||
</resultMap>
|
||||
|
||||
</mapper>
|
||||
|
|
@ -5,8 +5,9 @@
|
|||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.jeequan.jeepay.core.entity.MchDivisionReceiver">
|
||||
<id column="receiver_id" property="receiverId" />
|
||||
<result column="receiver_alias" property="receiverAlias" />
|
||||
<result column="receiver_group_id" property="receiverGroupId" />
|
||||
<result column="receiver_name" property="receiverName" />
|
||||
<result column="receiver_group_name" property="receiverGroupName" />
|
||||
<result column="mch_no" property="mchNo" />
|
||||
<result column="isv_no" property="isvNo" />
|
||||
<result column="app_id" property="appId" />
|
||||
|
|
@ -18,7 +19,6 @@
|
|||
<result column="relation_type_name" property="relationTypeName" />
|
||||
<result column="division_profit" property="divisionProfit" />
|
||||
<result column="state" property="state" />
|
||||
<result column="channel_bind_state" property="channelBindState" />
|
||||
<result column="channel_bind_result" property="channelBindResult" />
|
||||
<result column="channel_ext_info" property="channelExtInfo" />
|
||||
<result column="bind_success_time" property="bindSuccessTime" />
|
||||
|
|
|
|||
|
|
@ -13,4 +13,7 @@ import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
|||
*/
|
||||
public interface PayOrderDivisionRecordMapper extends BaseMapper<PayOrderDivisionRecord> {
|
||||
|
||||
/** 查询全部分账成功金额 **/
|
||||
Long sumSuccessDivisionAmount(String payOrderId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
<result column="channel_resp_result" property="channelRespResult" />
|
||||
<result column="receiver_id" property="receiverId" />
|
||||
<result column="receiver_group_id" property="receiverGroupId" />
|
||||
<result column="receiver_alias" property="receiverAlias" />
|
||||
<result column="acc_type" property="accType" />
|
||||
<result column="acc_no" property="accNo" />
|
||||
<result column="acc_name" property="accName" />
|
||||
|
|
@ -32,4 +33,11 @@
|
|||
<result column="updated_at" property="updatedAt" />
|
||||
</resultMap>
|
||||
|
||||
|
||||
<select id="sumSuccessDivisionAmount" resultType="Long">
|
||||
select ifnull(sum(cal_division_amount), 0) from t_pay_order_division_record
|
||||
where pay_order_id = #{payOrderId} and state = 1
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
<result column="amount" property="amount" />
|
||||
<result column="mch_fee_rate" property="mchFeeRate" />
|
||||
<result column="mch_fee_amount" property="mchFeeAmount" />
|
||||
<result column="mch_income_amount" property="mchIncomeAmount" />
|
||||
<result column="currency" property="currency" />
|
||||
<result column="state" property="state" />
|
||||
<result column="notify_state" property="notifyState" />
|
||||
|
|
|
|||
4
pom.xml
4
pom.xml
|
|
@ -42,7 +42,7 @@
|
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 项目构建输出编码 -->
|
||||
|
||||
<!-- 其他工具包 -->
|
||||
<jeepay.sdk.java.version>1.2.0</jeepay.sdk.java.version>
|
||||
<jeepay.sdk.java.version>1.3.0</jeepay.sdk.java.version>
|
||||
<fastjson.version>1.2.76</fastjson.version> <!-- fastjson -->
|
||||
<mybatis.plus.starter.version>3.4.2</mybatis.plus.starter.version> <!-- mybatis plus -->
|
||||
<hutool.util.version>5.6.6</hutool.util.version> <!-- hutool -->
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.13.50.ALL</version>
|
||||
<version>4.16.11.ALL</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里云oss组件 -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue