!542 同步支付中心、商城最新实现

Merge pull request !542 from 芋道源码/feature/mall_product
This commit is contained in:
芋道源码 2023-07-25 11:09:10 +00:00 committed by Gitee
commit 999dfd7c4a
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
718 changed files with 27005 additions and 15092 deletions

View File

@ -160,12 +160,11 @@
| | 功能 | 描述 |
|-----|------|---------------------------|
| 🚀 | 商户信息 | 管理商户信息,支持 Saas 场景下的多商户功能 |
| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 |
| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 |
| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 |
ps核心功能已经实现正在对接微信小程序中...
| 🚀 | 回调通知 | 查看支付回调业务的【支付】【退款】的通知结果 |
| 🚀 | 接入示例 | 提供接入支付系统的【支付】【退款】的功能实战 |
### 基础设施

View File

@ -1797,27 +1797,112 @@ INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT"
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2046,'满减送活动关闭','promotion:reward-activity:close',3,5,2041,'','','',null,0,1,1,1,'1','2022-11-05 10:42:53','1','2022-11-05 10:42:53',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2047,'限时折扣活动','',2,7,2030,'discount-activity','time','mall/promotion/discountActivity/index','PromotionDiscountActivity',0,1,1,1,'','2022-11-05 17:12:15','1','2023-04-08 11:45:44',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2048,'限时折扣活动查询','promotion:discount-activity:query',3,1,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:15','','2022-11-05 17:12:15',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2049,'限时折扣活动创建','promotion:discount-activity:create',3,2,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:15','','2022-11-05 17:12:15',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2050,'限时折扣活动更新','promotion:discount-activity:update',3,3,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:16','','2022-11-05 17:12:16',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2051,'限时折扣活动删除','promotion:discount-activity:delete',3,4,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:16','','2022-11-05 17:12:16',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2052,'限时折扣活动关闭','promotion:discount-activity:close',3,5,2047,'','','',null,0,1,1,1,'','2022-11-05 17:12:16','','2022-11-05 17:12:16',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2059,'秒杀活动管理','',2,0,2030,'seckill-activity','time-range','mall/promotion/seckill/seckillActivity/index','PromotionSeckillActivity',0,1,1,1,'','2022-11-06 22:24:49','1','2023-04-08 11:46:02',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2060,'秒杀活动查询','promotion:seckill-activity:query',3,1,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2061,'秒杀活动创建','promotion:seckill-activity:create',3,2,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2062,'秒杀活动更新','promotion:seckill-activity:update',3,3,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2063,'秒杀活动删除','promotion:seckill-activity:delete',3,4,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2064,'秒杀活动导出','promotion:seckill-activity:export',3,5,2059,'','','',null,0,1,1,1,'','2022-11-06 22:24:49','','2022-11-06 22:24:49',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2066,'秒杀时段管理','',2,0,2030,'seckill-time','','mall/promotion/seckill/seckillTime/index','PromotionSeckillTime',0,0,1,1,'','2022-11-15 19:46:50','1','2023-04-08 11:46:17',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2067,'秒杀时段查询','promotion:seckill-time:query',3,1,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2068,'秒杀时段创建','promotion:seckill-time:create',3,2,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2069,'秒杀时段更新','promotion:seckill-time:update',3,3,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2070,'秒杀时段删除','promotion:seckill-time:delete',3,4,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2071,'秒杀时段导出','promotion:seckill-time:export',3,5,2066,'','','',null,0,1,1,1,'','2022-11-15 19:46:51','','2022-11-15 19:46:51',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2072,'订单中心','',1,65,0,'/trade','order',null,null,0,1,1,1,'1','2022-11-19 18:57:19','1','2022-12-10 16:32:57',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2073,'售后退款','',2,1,2072,'trade/after-sale','education','mall/trade/afterSale/index','TradeAfterSale',0,1,1,1,'','2022-11-19 20:15:32','1','2023-04-08 11:43:19',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2074,'售后查询','trade:after-sale:query',3,1,2073,'','','',null,0,1,1,1,'','2022-11-19 20:15:33','1','2022-12-10 21:04:29',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2075,'秒杀活动关闭','promotion:sekill-activity:close',3,6,2059,'','','',null,0,1,1,1,'1','2022-11-28 20:20:15','1','2022-11-28 20:20:15',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2076,'订单列表','',2,0,2072,'trade/order','list','mall/trade/order/index','TradeOrder',0,1,1,1,'1','2022-12-10 21:05:44','1','2023-04-08 11:42:23',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2049, '限时折扣活动创建', 'promotion:discount-activity:create', 3, 2, 2047, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-05 17:12:15', '', '2022-11-05 17:12:15', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-05 17:12:16', '', '2022-11-05 17:12:16', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2051, '限时折扣活动删除', 'promotion:discount-activity:delete', 3, 4, 2047, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-05 17:12:16', '', '2022-11-05 17:12:16', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2052, '限时折扣活动关闭', 'promotion:discount-activity:close', 3, 5, 2047, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-05 17:12:16', '', '2022-11-05 17:12:16', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2059, '秒杀活动管理', '', 2, 0, 2030, 'seckill-activity', 'time-range',
'mall/promotion/seckill/seckillActivity/index', 'PromotionSeckillActivity', 0, 1, 1, 1, '',
'2022-11-06 22:24:49', '1', '2023-04-08 11:46:02', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2060, '秒杀活动查询', 'promotion:seckill-activity:query', 3, 1, 2059, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2061, '秒杀活动创建', 'promotion:seckill-activity:create', 3, 2, 2059, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2062, '秒杀活动更新', 'promotion:seckill-activity:update', 3, 3, 2059, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2063, '秒杀活动删除', 'promotion:seckill-activity:delete', 3, 4, 2059, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2064, '秒杀活动导出', 'promotion:seckill-activity:export', 3, 5, 2059, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-06 22:24:49', '', '2022-11-06 22:24:49', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2066, '秒杀时段管理', '', 2, 0, 2030, 'seckill-time', '', 'mall/promotion/seckill/SeckillConfig/index',
'PromotionSeckillConfig', 0, 0, 1, 1, '', '2022-11-15 19:46:50', '1', '2023-04-08 11:46:17', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2067, '秒杀时段查询', 'promotion:seckill-time:query', 3, 1, 2066, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2068, '秒杀时段创建', 'promotion:seckill-time:create', 3, 2, 2066, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2069, '秒杀时段更新', 'promotion:seckill-time:update', 3, 3, 2066, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2070, '秒杀时段删除', 'promotion:seckill-time:delete', 3, 4, 2066, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2071, '秒杀时段导出', 'promotion:seckill-time:export', 3, 5, 2066, '', '', '', null, 0, 1, 1, 1, '',
'2022-11-15 19:46:51', '', '2022-11-15 19:46:51', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2072, '订单中心', '', 1, 65, 0, '/trade', 'order', null, null, 0, 1, 1, 1, '1', '2022-11-19 18:57:19', '1',
'2022-12-10 16:32:57', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2073, '售后退款', '', 2, 1, 2072, 'trade/after-sale', 'education', 'mall/trade/afterSale/index',
'TradeAfterSale', 0, 1, 1, 1, '', '2022-11-19 20:15:32', '1', '2023-04-08 11:43:19', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2074, '售后查询', 'trade:after-sale:query', 3, 1, 2073, '', '', '', null, 0, 1, 1, 1, '', '2022-11-19 20:15:33',
'1', '2022-12-10 21:04:29', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2075, '秒杀活动关闭', 'promotion:sekill-activity:close', 3, 6, 2059, '', '', '', null, 0, 1, 1, 1, '1',
'2022-11-28 20:20:15', '1', '2022-11-28 20:20:15', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID", "NAME", "PERMISSION", "TYPE", "SORT", "PARENT_ID", "PATH", "ICON",
"COMPONENT", "COMPONENT_NAME", "STATUS", "VISIBLE", "KEEP_ALIVE",
"ALWAYS_SHOW", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED")
VALUES (2076, '订单列表', '', 2, 0, 2072, 'trade/order', 'list', 'mall/trade/order/index', 'TradeOrder', 0, 1, 1, 1,
'1', '2022-12-10 21:05:44', '1', '2023-04-08 11:42:23', 0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2077,'物流公司管理管理','',2,0,2072,'express-company','','mall/trade/expressCompany/index',null,0,1,1,1,'','2022-12-20 23:27:55','1','2022-12-20 23:36:20',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2078,'物流公司管理查询','trade:express-company:query',3,1,2077,'','','',null,0,1,1,1,'','2022-12-20 23:27:55','','2022-12-20 23:27:55',0);
INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_MENU"("ID","NAME","PERMISSION","TYPE","SORT","PARENT_ID","PATH","ICON","COMPONENT","COMPONENT_NAME","STATUS","VISIBLE","KEEP_ALIVE","ALWAYS_SHOW","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(2079,'物流公司管理创建','trade:express-company:create',3,2,2077,'','','',null,0,1,1,1,'','2022-12-20 23:27:55','','2022-12-20 23:27:55',0);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,7 @@
Target Server Version : 80026
File Encoding : 65001
Date: 13/04/2023 23:37:01
Date: 24/07/2023 08:51:31
*/
SET NAMES utf8mb4;
@ -73,6 +73,9 @@ CREATE TABLE `QRTZ_CRON_TRIGGERS` (
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai');
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
COMMIT;
-- ----------------------------
@ -133,6 +136,9 @@ CREATE TABLE `QRTZ_JOB_DETAILS` (
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000057400104A4F425F48414E444C45525F4E414D4574000C7061794E6F746966794A6F627800);
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000127400104A4F425F48414E444C45525F4E414D457400117061794F726465724578706972654A6F627800);
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000117400104A4F425F48414E444C45525F4E414D4574000F7061794F7264657253796E634A6F627800);
INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000137400104A4F425F48414E444C45525F4E414D45740010706179526566756E6453796E634A6F627800);
COMMIT;
-- ----------------------------
@ -185,7 +191,7 @@ CREATE TABLE `QRTZ_SCHEDULER_STATE` (
-- Records of QRTZ_SCHEDULER_STATE
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai1677076619095', 1677076631456, 15000);
INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai1690117495401', 1690119854263, 15000);
COMMIT;
-- ----------------------------
@ -279,202 +285,10 @@ CREATE TABLE `QRTZ_TRIGGERS` (
-- Records of QRTZ_TRIGGERS
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1677076638000, 1677076637000, 5, 'WAITING', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
COMMIT;
-- ----------------------------
-- Table structure for bpm_form
-- ----------------------------
DROP TABLE IF EXISTS `bpm_form`;
CREATE TABLE `bpm_form` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '表单名',
`status` tinyint NOT NULL COMMENT '开启状态',
`conf` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '表单的配置',
`fields` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '表单项的数组',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义';
-- ----------------------------
-- Records of bpm_form
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for bpm_oa_leave
-- ----------------------------
DROP TABLE IF EXISTS `bpm_oa_leave`;
CREATE TABLE `bpm_oa_leave` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '请假表单主键',
`user_id` bigint NOT NULL COMMENT '申请人的用户编号',
`type` tinyint NOT NULL COMMENT '请假类型',
`reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请假原因',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime NOT NULL COMMENT '结束时间',
`day` tinyint NOT NULL COMMENT '请假天数',
`result` tinyint NOT NULL COMMENT '请假结果',
`process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '流程实例的编号',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 35 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表';
-- ----------------------------
-- Records of bpm_oa_leave
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for bpm_process_definition_ext
-- ----------------------------
DROP TABLE IF EXISTS `bpm_process_definition_ext`;
CREATE TABLE `bpm_process_definition_ext` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
`model_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程模型的编号',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '描述',
`form_type` tinyint NOT NULL COMMENT '表单类型',
`form_id` bigint NULL DEFAULT NULL COMMENT '表单编号',
`form_conf` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '表单的配置',
`form_fields` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '表单项的数组',
`form_custom_create_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '自定义表单的提交路径',
`form_custom_view_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '自定义表单的查看路径',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 141 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n';
-- ----------------------------
-- Records of bpm_process_definition_ext
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for bpm_process_instance_ext
-- ----------------------------
DROP TABLE IF EXISTS `bpm_process_instance_ext`;
CREATE TABLE `bpm_process_instance_ext` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`start_user_id` bigint NOT NULL COMMENT '发起流程的用户编号',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '流程实例的名字',
`process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程实例的编号',
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
`category` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '流程分类',
`status` tinyint NOT NULL COMMENT '流程实例的状态',
`result` tinyint NOT NULL COMMENT '流程实例的结果',
`end_time` datetime NULL DEFAULT NULL COMMENT '结束时间',
`form_variables` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '表单值',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 296 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展';
-- ----------------------------
-- Records of bpm_process_instance_ext
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for bpm_task_assign_rule
-- ----------------------------
DROP TABLE IF EXISTS `bpm_task_assign_rule`;
CREATE TABLE `bpm_task_assign_rule` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`model_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程模型的编号',
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
`task_definition_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程任务定义的 key',
`type` tinyint NOT NULL COMMENT '规则类型',
`options` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '规则值JSON 数组',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 275 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表';
-- ----------------------------
-- Records of bpm_task_assign_rule
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for bpm_task_ext
-- ----------------------------
DROP TABLE IF EXISTS `bpm_task_ext`;
CREATE TABLE `bpm_task_ext` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`assignee_user_id` bigint NULL DEFAULT NULL COMMENT '任务的审批人',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '任务的名字',
`task_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '任务的编号',
`result` tinyint NOT NULL COMMENT '任务的结果',
`reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '审批建议',
`end_time` datetime NULL DEFAULT NULL COMMENT '任务的结束时间',
`process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程实例的编号',
`process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 351 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表';
-- ----------------------------
-- Records of bpm_task_ext
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for bpm_user_group
-- ----------------------------
DROP TABLE IF EXISTS `bpm_user_group`;
CREATE TABLE `bpm_user_group` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '组名',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '描述',
`member_user_ids` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '成员编号数组',
`status` tinyint NOT NULL COMMENT '状态0正常 1停用',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 113 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组';
-- ----------------------------
-- Records of bpm_user_group
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1688907102000, 1688907101000, 5, 'PAUSED', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', 'payOrderExpireJob', 'DEFAULT', NULL, 1690011600000, -1, 5, 'PAUSED', 'CRON', 1690011553000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', 'payOrderSyncJob', 'DEFAULT', NULL, 1690011600000, 1690011540000, 5, 'PAUSED', 'CRON', 1690007785000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', 'payRefundSyncJob', 'DEFAULT', NULL, 1690117560000, 1690117500000, 5, 'PAUSED', 'CRON', 1690117424000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
COMMIT;
-- ----------------------------
@ -546,7 +360,7 @@ CREATE TABLE `infra_api_error_log` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1110 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
) ENGINE = InnoDB AUTO_INCREMENT = 1391 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
-- ----------------------------
-- Records of infra_api_error_log
@ -584,7 +398,7 @@ CREATE TABLE `infra_codegen_column` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1688 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
) ENGINE = InnoDB AUTO_INCREMENT = 1715 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
-- ----------------------------
-- Records of infra_codegen_column
@ -617,7 +431,7 @@ CREATE TABLE `infra_codegen_table` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 131 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
) ENGINE = InnoDB AUTO_INCREMENT = 132 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
-- ----------------------------
-- Records of infra_codegen_table
@ -644,7 +458,7 @@ CREATE TABLE `infra_config` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '参数配置表';
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '参数配置表';
-- ----------------------------
-- Records of infra_config
@ -655,6 +469,7 @@ INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `val
INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 'url', 2, 'SkyWalking 监控的地址', 'url.skywalking', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:57:03', b'0');
INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (9, 'url', 2, 'Spring Boot Admin 监控的地址', 'url.spring-boot-admin', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:52:07', b'0');
INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (10, 'url', 2, 'Swagger 接口文档的地址', 'url.swagger', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:59:00', b'0');
INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (11, 'ui', 2, '腾讯地图 key', 'tencent.lbs.key', 'TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E', b'1', '腾讯地图 key', '1', '2023-06-03 19:16:27', '1', '2023-06-03 19:16:27', b'0');
COMMIT;
-- ----------------------------
@ -699,7 +514,7 @@ CREATE TABLE `infra_file` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 912 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
) ENGINE = InnoDB AUTO_INCREMENT = 953 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
-- ----------------------------
-- Records of infra_file
@ -753,7 +568,7 @@ CREATE TABLE `infra_file_content` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
) ENGINE = InnoDB AUTO_INCREMENT = 44 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
-- ----------------------------
-- Records of infra_file_content
@ -781,14 +596,17 @@ CREATE TABLE `infra_job` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
-- ----------------------------
-- Records of infra_job
-- ----------------------------
BEGIN;
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 1, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2022-11-24 23:01:35', b'0');
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2023-07-09 20:51:41', b'0');
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (16, 'Job 示例', 1, 'demoJob', NULL, '* * * L * ?', 1, 1, 0, '1', '2022-09-24 22:31:41', '1', '2022-09-24 22:31:42', b'0');
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (17, '支付订单同步 Job', 2, 'payOrderSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 14:36:26', '1', '2023-07-22 15:39:08', b'0');
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (18, '支付订单过期 Job', 2, 'payOrderExpireJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 15:36:23', '1', '2023-07-22 15:39:54', b'0');
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (19, '退款订单的同步 Job', 2, 'payRefundSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-23 21:03:44', '1', '2023-07-23 21:09:00', b'0');
COMMIT;
-- ----------------------------
@ -812,7 +630,7 @@ CREATE TABLE `infra_job_log` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 168767 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
) ENGINE = InnoDB AUTO_INCREMENT = 161 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
-- ----------------------------
-- Records of infra_job_log
@ -867,7 +685,7 @@ CREATE TABLE `member_user` (
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
) ENGINE = InnoDB AUTO_INCREMENT = 247 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户';
) ENGINE = InnoDB AUTO_INCREMENT = 248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户';
-- ----------------------------
-- Records of member_user
@ -875,294 +693,6 @@ CREATE TABLE `member_user` (
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_app
-- ----------------------------
DROP TABLE IF EXISTS `pay_app`;
CREATE TABLE `pay_app` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '应用编号',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名',
`status` tinyint NOT NULL COMMENT '开启状态',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
`pay_notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付结果的回调地址',
`refund_notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退款结果的回调地址',
`merchant_id` bigint NOT NULL COMMENT '商户编号',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付应用信息';
-- ----------------------------
-- Records of pay_app
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_channel
-- ----------------------------
DROP TABLE IF EXISTS `pay_channel`;
CREATE TABLE `pay_channel` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商户编号',
`code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道编码',
`status` tinyint NOT NULL COMMENT '开启状态',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
`fee_rate` double NOT NULL DEFAULT 0 COMMENT '渠道费率单位百分比',
`merchant_id` bigint NOT NULL COMMENT '商户编号',
`app_id` bigint NOT NULL COMMENT '应用编号',
`config` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付渠道配置',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 22 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付渠道\n';
-- ----------------------------
-- Records of pay_channel
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_demo_order
-- ----------------------------
DROP TABLE IF EXISTS `pay_demo_order`;
CREATE TABLE `pay_demo_order` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号',
`user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号',
`spu_id` bigint NOT NULL COMMENT '商品编号',
`spu_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '商品名字',
`price` int NOT NULL COMMENT '价格单位',
`payed` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已支付[0:未支付 1:已经支付过]',
`pay_order_id` bigint NULL DEFAULT NULL COMMENT '支付订单编号',
`pay_channel_code` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '支付成功的支付渠道',
`pay_time` datetime NULL DEFAULT NULL COMMENT '订单支付时间',
`pay_refund_id` bigint NULL DEFAULT NULL COMMENT '退款订单编号',
`refund_price` int NOT NULL DEFAULT 0 COMMENT '退款金额单位',
`refund_time` datetime NULL DEFAULT NULL COMMENT '退款时间',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 72 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '示例订单\n';
-- ----------------------------
-- Records of pay_demo_order
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_merchant
-- ----------------------------
DROP TABLE IF EXISTS `pay_merchant`;
CREATE TABLE `pay_merchant` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商户编号',
`no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户号',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户全称',
`short_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户简称',
`status` tinyint NOT NULL COMMENT '开启状态',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付商户信息';
-- ----------------------------
-- Records of pay_merchant
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_notify_log
-- ----------------------------
DROP TABLE IF EXISTS `pay_notify_log`;
CREATE TABLE `pay_notify_log` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志编号',
`task_id` bigint NOT NULL COMMENT '通知任务编号',
`notify_times` tinyint NOT NULL COMMENT '第几次被通知',
`response` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求参数',
`status` tinyint NOT NULL COMMENT '通知状态',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 371964 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付通知 App 的日志';
-- ----------------------------
-- Records of pay_notify_log
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_notify_task
-- ----------------------------
DROP TABLE IF EXISTS `pay_notify_task`;
CREATE TABLE `pay_notify_task` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务编号',
`merchant_id` bigint NOT NULL COMMENT '商户编号',
`app_id` bigint NOT NULL COMMENT '应用编号',
`type` tinyint NOT NULL COMMENT '通知类型',
`data_id` bigint NOT NULL COMMENT '数据编号',
`status` tinyint NOT NULL COMMENT '通知状态',
`merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户订单编号',
`next_notify_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '下一次通知时间',
`last_execute_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后一次执行时间',
`notify_times` tinyint NOT NULL COMMENT '当前通知次数',
`max_notify_times` tinyint NOT NULL COMMENT '最大可通知次数',
`notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异步通知地址',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 151 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商户支付退款等的通知\n';
-- ----------------------------
-- Records of pay_notify_task
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_order
-- ----------------------------
DROP TABLE IF EXISTS `pay_order`;
CREATE TABLE `pay_order` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '支付订单编号',
`merchant_id` bigint NOT NULL COMMENT '商户编号',
`app_id` bigint NOT NULL COMMENT '应用编号',
`channel_id` bigint NULL DEFAULT NULL COMMENT '渠道编号',
`channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '渠道编码',
`merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户订单编号',
`subject` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品标题',
`body` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品描述',
`notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异步通知地址',
`notify_status` tinyint NOT NULL COMMENT '通知商户支付结果的回调状态',
`amount` bigint NOT NULL COMMENT '支付金额单位',
`channel_fee_rate` double NULL DEFAULT 0 COMMENT '渠道手续费单位百分比',
`channel_fee_amount` bigint NULL DEFAULT 0 COMMENT '渠道手续金额单位',
`status` tinyint NOT NULL COMMENT '支付状态',
`user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP',
`expire_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '订单失效时间',
`success_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '订单支付成功时间',
`notify_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '订单支付通知时间',
`success_extension_id` bigint NULL DEFAULT NULL COMMENT '支付成功的订单拓展单编号',
`refund_status` tinyint NOT NULL COMMENT '退款状态',
`refund_times` tinyint NOT NULL COMMENT '退款次数',
`refund_amount` bigint NOT NULL COMMENT '退款总金额单位',
`channel_user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '渠道用户编号',
`channel_order_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '渠道订单号',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 171 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n';
-- ----------------------------
-- Records of pay_order
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_order_extension
-- ----------------------------
DROP TABLE IF EXISTS `pay_order_extension`;
CREATE TABLE `pay_order_extension` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '支付订单编号',
`no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付订单号',
`order_id` bigint NOT NULL COMMENT '支付订单编号',
`channel_id` bigint NOT NULL COMMENT '渠道编号',
`channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道编码',
`user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP',
`status` tinyint NOT NULL COMMENT '支付状态',
`channel_extras` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '支付渠道的额外参数',
`channel_notify_data` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 383 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n';
-- ----------------------------
-- Records of pay_order_extension
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for pay_refund
-- ----------------------------
DROP TABLE IF EXISTS `pay_refund`;
CREATE TABLE `pay_refund` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '支付退款编号',
`merchant_id` bigint NOT NULL COMMENT '商户编号',
`app_id` bigint NOT NULL COMMENT '应用编号',
`channel_id` bigint NOT NULL COMMENT '渠道编号',
`channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道编码',
`order_id` bigint NOT NULL COMMENT '支付订单编号 pay_order 表id',
`trade_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '交易订单号 pay_extension 表no 字段',
`merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户订单编号商户系统生成',
`merchant_refund_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户退款订单号商户系统生成',
`notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异步通知商户地址',
`notify_status` tinyint NOT NULL COMMENT '通知商户退款结果的回调状态',
`status` tinyint NOT NULL COMMENT '退款状态',
`type` tinyint NOT NULL COMMENT '退款类型(部分退款全部退款)',
`pay_amount` bigint NOT NULL COMMENT '支付金额,单位分',
`refund_amount` bigint NOT NULL COMMENT '退款金额,单位分',
`reason` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退款原因',
`user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户 IP',
`channel_order_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道订单号pay_order 中的channel_order_no 对应',
`channel_refund_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '渠道退款单号渠道返回',
`channel_error_code` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '渠道调用报错时错误码',
`channel_error_msg` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '渠道调用报错时错误信息',
`channel_extras` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '支付渠道的额外参数',
`expire_time` datetime NULL DEFAULT NULL COMMENT '退款失效时间',
`success_time` datetime NULL DEFAULT NULL COMMENT '退款成功时间',
`notify_time` datetime NULL DEFAULT NULL COMMENT '退款通知时间',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '退款订单';
-- ----------------------------
-- Records of pay_refund
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for system_dept
-- ----------------------------
@ -1223,7 +753,7 @@ CREATE TABLE `system_dict_data` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1234 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
) ENGINE = InnoDB AUTO_INCREMENT = 1348 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
-- ----------------------------
-- Records of system_dict_data
@ -1299,33 +829,22 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (86, 0, '病假', '1', 'bpm_oa_leave_type', 0, 'primary', '', NULL, '1', '2021-09-21 22:35:28', '1', '2022-02-16 10:00:41', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (87, 1, '事假', '2', 'bpm_oa_leave_type', 0, 'info', '', NULL, '1', '2021-09-21 22:36:11', '1', '2022-02-16 10:00:49', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (88, 2, '婚假', '3', 'bpm_oa_leave_type', 0, 'warning', '', NULL, '1', '2021-09-21 22:36:38', '1', '2022-02-16 10:00:53', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (98, 1, 'v2', 'v2', 'pay_channel_wechat_version', 0, '', '', 'v2版本', '1', '2021-11-08 17:00:58', '1', '2021-11-08 17:00:58', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (99, 2, 'v3', 'v3', 'pay_channel_wechat_version', 0, '', '', 'v3版本', '1', '2021-11-08 17:01:07', '1', '2021-11-08 17:01:07', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (108, 1, 'RSA2', 'RSA2', 'pay_channel_alipay_sign_type', 0, '', '', 'RSA2', '1', '2021-11-18 15:39:29', '1', '2021-11-18 15:39:29', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (109, 1, '公钥模式', '1', 'pay_channel_alipay_mode', 0, '', '', '公钥模式privateKey + alipayPublicKey', '1', '2021-11-18 15:45:23', '1', '2021-11-18 15:45:23', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (110, 2, '证书模式', '2', 'pay_channel_alipay_mode', 0, '', '', '证书模式appCertContent + alipayPublicCertContent + rootCertContent', '1', '2021-11-18 15:45:40', '1', '2021-11-18 15:45:40', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (111, 1, '线上', 'https://openapi.alipay.com/gateway.do', 'pay_channel_alipay_server_type', 0, '', '', '网关地址 - 线上', '1', '2021-11-18 16:59:32', '1', '2021-11-21 17:37:29', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (112, 2, '沙箱', 'https://openapi.alipaydev.com/gateway.do', 'pay_channel_alipay_server_type', 0, '', '', '网关地址 - 沙箱', '1', '2021-11-18 16:59:48', '1', '2021-11-21 17:37:39', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (113, 1, '微信 JSAPI 支付', 'wx_pub', 'pay_channel_code_type', 0, '', '', '微信 JSAPI公众号 支付', '1', '2021-12-03 10:40:24', '1', '2021-12-04 16:41:00', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (114, 2, '微信小程序支付', 'wx_lite', 'pay_channel_code_type', 0, '', '', '微信小程序支付', '1', '2021-12-03 10:41:06', '1', '2021-12-03 10:41:06', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (115, 3, '微信 App 支付', 'wx_app', 'pay_channel_code_type', 0, '', '', '微信 App 支付', '1', '2021-12-03 10:41:20', '1', '2021-12-03 10:41:20', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (116, 4, '支付宝 PC 网站支付', 'alipay_pc', 'pay_channel_code_type', 0, '', '', '支付宝 PC 网站支付', '1', '2021-12-03 10:42:09', '1', '2021-12-03 10:42:09', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (117, 5, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code_type', 0, '', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2021-12-03 10:42:26', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (118, 6, '支付宝App 支付', 'alipay_app', 'pay_channel_code_type', 0, '', '', '支付宝App 支付', '1', '2021-12-03 10:42:55', '1', '2021-12-03 10:42:55', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (119, 7, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code_type', 0, '', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2021-12-03 10:43:10', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (120, 1, '通知成功', '10', 'pay_order_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2022-02-16 13:59:13', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, 2, '通知失败', '20', 'pay_order_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2022-02-16 13:59:17', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, 3, '未通知', '0', 'pay_order_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2022-02-16 13:59:23', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (123, 1, '支付成功', '10', 'pay_order_status', 0, 'success', '', '支付成功', '1', '2021-12-03 11:18:29', '1', '2022-02-16 15:24:25', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (124, 2, '支付关闭', '20', 'pay_order_status', 0, 'danger', '', '支付关闭', '1', '2021-12-03 11:18:42', '1', '2022-02-16 15:24:31', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (125, 3, '未支付', '0', 'pay_order_status', 0, 'info', '', '未支付', '1', '2021-12-03 11:18:18', '1', '2022-02-16 15:24:35', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (126, 1, '未退款', '0', 'pay_order_refund_status', 0, '', '', '未退款', '1', '2021-12-03 11:30:35', '1', '2021-12-03 11:34:05', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (127, 2, '部分退款', '10', 'pay_order_refund_status', 0, '', '', '部分退款', '1', '2021-12-03 11:30:44', '1', '2021-12-03 11:34:10', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (128, 3, '全部退款', '20', 'pay_order_refund_status', 0, '', '', '全部退款', '1', '2021-12-03 11:30:52', '1', '2021-12-03 11:34:14', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1117, 1, '退款订单生成', '0', 'pay_refund_order_status', 0, 'primary', '', '退款订单生成', '1', '2021-12-10 16:44:44', '1', '2022-02-16 14:05:24', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, 2, '退款成功', '1', 'pay_refund_order_status', 0, 'success', '', '退款成功', '1', '2021-12-10 16:44:59', '1', '2022-02-16 14:05:28', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, 3, '退款失败', '2', 'pay_refund_order_status', 0, 'danger', '', '退款失败', '1', '2021-12-10 16:45:10', '1', '2022-02-16 14:05:34', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1124, 8, '退款关闭', '99', 'pay_refund_order_status', 0, 'info', '', '退款关闭', '1', '2021-12-10 16:46:26', '1', '2022-02-16 14:05:40', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (113, 1, '微信公众号支付', 'wx_pub', 'pay_channel_code', 0, 'success', '', '微信公众号支付', '1', '2021-12-03 10:40:24', '1', '2023-07-19 20:08:47', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (114, 2, '微信小程序支付', 'wx_lite', 'pay_channel_code', 0, 'success', '', '微信小程序支付', '1', '2021-12-03 10:41:06', '1', '2023-07-19 20:08:50', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (115, 3, '微信 App 支付', 'wx_app', 'pay_channel_code', 0, 'success', '', '微信 App 支付', '1', '2021-12-03 10:41:20', '1', '2023-07-19 20:08:56', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (116, 10, '支付宝 PC 网站支付', 'alipay_pc', 'pay_channel_code', 0, 'primary', '', '支付宝 PC 网站支付', '1', '2021-12-03 10:42:09', '1', '2023-07-19 20:09:12', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (123, 10, '支付成功', '10', 'pay_order_status', 0, 'success', '', '支付成功', '1', '2021-12-03 11:18:29', '1', '2023-07-19 18:04:28', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (124, 30, '支付关闭', '30', 'pay_order_status', 0, 'info', '', '支付关闭', '1', '2021-12-03 11:18:42', '1', '2023-07-19 18:05:07', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (125, 0, '等待支付', '0', 'pay_order_status', 0, 'info', '', '未支付', '1', '2021-12-03 11:18:18', '1', '2023-07-19 18:04:15', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, 0, '等待退款', '0', 'pay_refund_status', 0, 'info', '', '等待退款', '1', '2021-12-10 16:44:59', '1', '2023-07-19 10:14:39', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, 20, '退款失败', '20', 'pay_refund_status', 0, 'danger', '', '退款失败', '1', '2021-12-10 16:45:10', '1', '2023-07-19 10:15:10', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1124, 10, '退款成功', '10', 'pay_refund_status', 0, 'success', '', '退款成功', '1', '2021-12-10 16:46:26', '1', '2023-07-19 10:15:00', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1125, 0, '默认', '1', 'bpm_model_category', 0, 'primary', '', '流程分类 - 默认', '1', '2022-01-02 08:41:11', '1', '2022-02-16 20:01:42', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1126, 0, 'OA', '2', 'bpm_model_category', 0, 'success', '', '流程分类 - OA', '1', '2022-01-02 08:41:22', '1', '2022-02-16 20:01:50', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1127, 0, '进行中', '1', 'bpm_process_instance_status', 0, 'primary', '', '流程实例的状态 - 进行中', '1', '2022-01-07 23:47:22', '1', '2022-02-16 20:07:49', b'0');
@ -1348,9 +867,6 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1144, 21, '流程发起人的二级领导', '21', 'bpm_task_assign_script', 0, '', '', '任务分配自定义脚本 - 流程发起人的二级领导', '103', '2022-01-15 21:24:46', '103', '2022-01-15 21:24:57', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1145, 1, '管理后台', '1', 'infra_codegen_scene', 0, '', '', '代码生成的场景枚举 - 管理后台', '1', '2022-02-02 13:15:06', '1', '2022-03-10 16:32:59', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1146, 2, '用户 APP', '2', 'infra_codegen_scene', 0, '', '', '代码生成的场景枚举 - 用户 APP', '1', '2022-02-02 13:15:19', '1', '2022-03-10 16:33:03', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1147, 0, '未退款', '0', 'pay_refund_order_type', 0, 'info', '', '退款类型 - 未退款', '1', '2022-02-16 14:09:01', '1', '2022-02-16 14:09:01', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1148, 10, '部分退款', '10', 'pay_refund_order_type', 0, 'success', '', '退款类型 - 部分退款', '1', '2022-02-16 14:09:25', '1', '2022-02-16 14:11:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1149, 20, '全部退款', '20', 'pay_refund_order_type', 0, 'warning', '', '退款类型 - 全部退款', '1', '2022-02-16 14:11:33', '1', '2022-02-16 14:11:33', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1150, 1, '数据库', '1', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:25:28', '1', '2022-03-15 00:25:28', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1151, 10, '本地磁盘', '10', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:25:41', '1', '2022-03-15 00:25:56', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1152, 11, 'FTP 服务器', '11', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:26:06', '1', '2022-03-15 00:26:10', b'0');
@ -1429,12 +945,37 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1226, 30, '不发送', '30', 'system_mail_send_status', 0, 'info', '', '邮件发送状态 - 不发送', '1', '2023-01-26 09:55:06', '1', '2023-01-26 16:36:36', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1227, 1, '通知公告', '1', 'system_notify_template_type', 0, 'primary', '', '站内信模版的类型 - 通知公告', '1', '2023-01-28 10:35:59', '1', '2023-01-28 10:35:59', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1228, 2, '系统消息', '2', 'system_notify_template_type', 0, 'success', '', '站内信模版的类型 - 系统消息', '1', '2023-01-28 10:36:20', '1', '2023-01-28 10:36:25', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1229, 0, '模拟支付', 'mock', 'pay_channel_code_type', 0, 'default', '', NULL, '1', '2023-02-12 21:50:22', '1', '2023-02-12 21:50:22', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1230, 8, '支付宝条码支付', 'alipay_bar', 'pay_channel_code_type', 0, 'default', '', NULL, '1', '2023-02-18 23:32:24', '1', '2023-02-18 23:32:32', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1229, 0, '模拟支付', 'mock', 'pay_channel_code', 0, 'default', '', '模拟支付', '1', '2023-02-12 21:50:22', '1', '2023-07-10 10:11:02', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1230, 13, '支付宝条码支付', 'alipay_bar', 'pay_channel_code', 0, 'primary', '', '支付宝条码支付', '1', '2023-02-18 23:32:24', '1', '2023-07-19 20:09:23', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1231, 10, 'Vue2 Element UI 标准模版', '10', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:03:55', '1', '2023-04-13 00:03:55', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1232, 20, 'Vue3 Element Plus 标准模版', '20', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:08', '1', '2023-04-13 00:04:08', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1233, 21, 'Vue3 Element Plus Schema 模版', '21', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:26', '1', '2023-04-13 00:04:26', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1234, 30, 'Vue3 vben 模版', '30', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:26', '1', '2023-04-13 00:04:26', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1235, 1, '个', '1', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1236, 1, '件', '2', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1237, 1, '盒', '3', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1238, 1, '袋', '4', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1239, 1, '箱', '5', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1240, 1, '套', '6', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1241, 1, '包', '7', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1242, 1, '双', '8', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1243, 1, '卷', '9', 'product_unit', 0, '', '', '', '1', '2023-05-23 14:38:38', '1', '2023-05-23 14:38:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1244, 0, '按件', '1', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:40', '1', '2023-05-21 22:46:40', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1245, 1, '按重量', '2', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:58', '1', '2023-05-21 22:46:58', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1246, 2, '按体积', '3', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:47:18', '1', '2023-05-21 22:47:18', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1335, 1, '购物', '1', 'member_point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:27', '1', '2023-06-28 13:48:28', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1336, 2, '签到', '2', 'member_point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:48', '1', '2023-06-28 13:48:31', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1337, 1, '订单创建', '1', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:16:42', '1', '2023-06-28 13:48:34', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1338, 2, '冻结期', '2', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:16:58', '1', '2023-06-28 13:48:36', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1339, 3, '完成', '3', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:17:07', '1', '2023-06-28 13:48:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1340, 4, '失效(订单退款)', '4', 'member_point_status', 0, '', '', '', '1', '2023-06-10 12:17:21', '1', '2023-06-28 13:48:42', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1341, 20, '已退款', '20', 'pay_order_status', 0, 'danger', '', '已退款', '1', '2023-07-19 18:05:37', '1', '2023-07-19 18:05:37', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1342, 21, '请求成功但是结果失败', '21', 'pay_notify_status', 0, 'warning', '', '请求成功但是结果失败', '1', '2023-07-19 18:10:47', '1', '2023-07-19 18:11:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1343, 22, '请求失败', '22', 'pay_notify_status', 0, 'warning', '', NULL, '1', '2023-07-19 18:11:05', '1', '2023-07-19 18:11:27', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1344, 4, '微信扫码支付', 'wx_native', 'pay_channel_code', 0, 'success', '', '微信扫码支付', '1', '2023-07-19 20:07:47', '1', '2023-07-19 20:09:03', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1345, 5, '微信条码支付', 'wx_bar', 'pay_channel_code', 0, 'success', '', '微信条码支付\n', '1', '2023-07-19 20:08:06', '1', '2023-07-19 20:09:08', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1346, 1, '支付单', '1', 'pay_notify_type', 0, 'primary', '', '支付单', '1', '2023-07-20 12:23:17', '1', '2023-07-20 12:23:17', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1347, 2, '退款单', '2', 'pay_notify_type', 0, 'danger', '', NULL, '1', '2023-07-20 12:23:26', '1', '2023-07-20 12:23:26', b'0');
COMMIT;
-- ----------------------------
@ -1455,7 +996,7 @@ CREATE TABLE `system_dict_type` (
`deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 169 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
) ENGINE = InnoDB AUTO_INCREMENT = 174 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
-- ----------------------------
-- Records of system_dict_type
@ -1481,16 +1022,10 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (115, '错误码的类型', 'system_error_code_type', 0, NULL, '1', '2021-04-21 00:06:30', '1', '2022-02-01 16:36:49', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (116, '登陆日志的类型', 'system_login_type', 0, '登陆日志的类型', '1', '2021-10-06 00:50:46', '1', '2022-02-01 16:35:56', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (117, 'OA 请假类型', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:34:33', '1', '2022-01-22 10:41:37', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (122, '支付渠道微信版本', 'pay_channel_wechat_version', 0, '支付渠道微信版本', '1', '2021-11-08 17:00:26', '1', '2021-11-08 17:00:26', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (127, '支付渠道支付宝算法类型', 'pay_channel_alipay_sign_type', 0, '支付渠道支付宝算法类型', '1', '2021-11-18 15:39:09', '1', '2021-11-18 15:39:09', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (128, '支付渠道支付宝公钥类型', 'pay_channel_alipay_mode', 0, '支付渠道支付宝公钥类型', '1', '2021-11-18 15:44:28', '1', '2021-11-18 15:44:28', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (129, '支付宝网关地址', 'pay_channel_alipay_server_type', 0, '支付宝网关地址', '1', '2021-11-18 16:58:55', '1', '2021-11-18 17:01:34', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (130, '支付渠道编码类型', 'pay_channel_code_type', 0, '支付渠道的编码', '1', '2021-12-03 10:35:08', '1', '2021-12-03 10:35:08', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (131, '支付订单回调状态', 'pay_order_notify_status', 0, '支付订单回调状态', '1', '2021-12-03 10:53:29', '1', '2021-12-03 10:53:29', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (130, '支付渠道编码类型', 'pay_channel_code', 0, '支付渠道的编码', '1', '2021-12-03 10:35:08', '1', '2023-07-10 10:11:39', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (131, '支付回调状态', 'pay_notify_status', 0, '支付回调状态包括退款回调', '1', '2021-12-03 10:53:29', '1', '2023-07-19 18:09:43', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (132, '支付订单状态', 'pay_order_status', 0, '支付订单状态', '1', '2021-12-03 11:17:50', '1', '2021-12-03 11:17:50', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (133, '支付订单退款状态', 'pay_order_refund_status', 0, '支付订单退款状态', '1', '2021-12-03 11:27:31', '1', '2021-12-03 11:27:31', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (134, '退款订单状态', 'pay_refund_order_status', 0, '退款订单状态', '1', '2021-12-10 16:42:50', '1', '2021-12-10 16:42:50', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (135, '退款订单类别', 'pay_refund_order_type', 0, '退款订单类别', '1', '2021-12-10 17:14:53', '1', '2021-12-10 17:14:53', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (134, '退款订单状态', 'pay_refund_status', 0, '退款订单状态', '1', '2021-12-10 16:42:50', '1', '2023-07-19 10:13:17', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (138, '流程分类', 'bpm_model_category', 0, '流程分类', '1', '2022-01-02 08:40:45', '1', '2022-01-02 08:40:45', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (139, '流程实例的状态', 'bpm_process_instance_status', 0, '流程实例的状态', '1', '2022-01-07 23:46:42', '1', '2022-01-07 23:46:42', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (140, '流程实例的结果', 'bpm_process_instance_result', 0, '流程实例的结果', '1', '2022-01-07 23:48:10', '1', '2022-01-07 23:48:10', b'0', NULL);
@ -1521,6 +1056,11 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (166, '邮件发送状态', 'system_mail_send_status', 0, '邮件发送状态', '1', '2023-01-26 09:53:13', '1', '2023-01-26 09:53:13', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (167, '站内信模版的类型', 'system_notify_template_type', 0, '站内信模版的类型', '1', '2023-01-28 10:35:10', '1', '2023-01-28 10:35:10', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (168, '代码生成的前端类型', 'infra_codegen_front_type', 0, '', '1', '2023-04-12 23:57:52', '1', '2023-04-12 23:57:52', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (169, '商品的单位', 'product_unit', 0, '商品的单位', '1', '2023-05-24 21:23:59', '1', '2023-05-24 21:23:59', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (170, '快递计费方式', 'trade_delivery_express_charge_mode', 0, '用于商城交易模块配送管理', '1', '2023-05-21 22:45:03', '1', '2023-05-21 22:45:03', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (171, '积分业务类型', 'member_point_biz_type', 0, '', '1', '2023-06-10 12:15:00', '1', '2023-06-28 13:48:20', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (172, '积分订单状态', 'member_point_status', 0, '', '1', '2023-06-10 12:16:27', '1', '2023-06-28 13:48:17', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (173, '支付通知类型', 'pay_notify_type', 0, NULL, '1', '2023-07-20 12:23:03', '1', '2023-07-20 12:23:03', b'0', '1970-01-01 00:00:00');
COMMIT;
-- ----------------------------
@ -1540,7 +1080,7 @@ CREATE TABLE `system_error_code` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
) ENGINE = InnoDB AUTO_INCREMENT = 5833 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
-- ----------------------------
-- Records of system_error_code
@ -1569,7 +1109,7 @@ CREATE TABLE `system_login_log` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2163 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
) ENGINE = InnoDB AUTO_INCREMENT = 2243 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
-- ----------------------------
-- Records of system_login_log
@ -1699,7 +1239,7 @@ CREATE TABLE `system_menu` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2162 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
) ENGINE = InnoDB AUTO_INCREMENT = 2303 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
-- ----------------------------
-- Records of system_menu
@ -1833,12 +1373,11 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, '请假查询', '', 2, 0, 5, 'leave', 'user', 'bpm/oa/leave/index', 'BpmOALeave', 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2023-04-08 11:30:40', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, '请假申请查询', 'bpm:oa-leave:query', 3, 1, 1118, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1120, '请假申请创建', 'bpm:oa-leave:create', 3, 2, 1118, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1126, '应用信息', '', 2, 1, 1117, 'app', 'table', 'pay/app/index', 'PayMerchant', 0, b'1', b'1', b'1', '', '2021-11-10 01:13:30', '1', '2023-04-08 10:43:14', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1126, '应用信息', '', 2, 1, 1117, 'app', 'table', 'pay/app/index', 'PayApp', 0, b'1', b'1', b'1', '', '2021-11-10 01:13:30', '1', '2023-07-20 12:13:32', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1127, '支付应用信息查询', 'pay:app:query', 3, 1, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1128, '支付应用信息创建', 'pay:app:create', 3, 2, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1129, '支付应用信息更新', 'pay:app:update', 3, 3, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1130, '支付应用信息删除', 'pay:app:delete', 3, 4, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1131, '支付应用信息导出', 'pay:app:export', 3, 5, 1126, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1132, '秘钥解析', 'pay:channel:parsing', 3, 6, 1129, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2021-11-08 15:15:47', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1133, '支付商户信息查询', 'pay:merchant:query', 3, 1, 1132, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:41', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1134, '支付商户信息创建', 'pay:merchant:create', 3, 2, 1132, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-11-10 01:13:41', '', '2022-04-20 17:03:10', b'0');
@ -1864,12 +1403,6 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1176, '支付订单更新', 'pay:order:update', 3, 3, 1173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1177, '支付订单删除', 'pay:order:delete', 3, 4, 1173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1178, '支付订单导出', 'pay:order:export', 3, 5, 1173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1179, '商户信息', '', 2, 0, 1117, 'merchant', 'merchant', 'pay/merchant/index', 'PayApp', 0, b'1', b'1', b'1', '', '2021-12-25 09:01:44', '1', '2023-04-08 10:42:32', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1180, '支付商户信息查询', 'pay:merchant:query', 3, 1, 1179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 09:01:44', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1181, '支付商户信息创建', 'pay:merchant:create', 3, 2, 1179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 09:01:44', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1182, '支付商户信息更新', 'pay:merchant:update', 3, 3, 1179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 09:01:44', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1183, '支付商户信息删除', '', 3, 4, 1179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 09:01:44', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1184, '支付商户信息导出', 'pay:merchant:export', 3, 5, 1179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-25 09:01:44', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1185, '工作流程', '', 1, 50, 0, '/bpm', 'tool', NULL, NULL, 0, b'1', b'1', b'1', '1', '2021-12-30 20:26:36', '103', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1186, '流程管理', '', 1, 10, 1185, 'manager', 'nested', NULL, NULL, 0, b'1', b'1', b'1', '1', '2021-12-30 20:28:30', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1187, '流程表单', '', 2, 0, 1186, 'form', 'form', 'bpm/form/index', 'BpmForm', 0, b'1', b'1', b'1', '', '2021-12-30 12:38:22', '1', '2023-04-08 10:50:37', b'0');
@ -1984,29 +1517,22 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2051, '限时折扣活动删除', 'promotion:discount-activity:delete', 3, 4, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2052, '限时折扣活动关闭', 'promotion:discount-activity:close', 3, 5, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2059, '秒杀活动管理', '', 2, 0, 2030, 'seckill-activity', 'time-range', 'mall/promotion/seckill/seckillActivity/index', 'PromotionSeckillActivity', 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '1', '2023-04-08 11:46:02', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2059, '秒杀商品', '', 2, 2, 2209, 'activity', 'ep:basketball', 'mall/promotion/seckill/activity/index', 'PromotionSeckillActivity', 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '1', '2023-06-24 18:57:25', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2060, '秒杀活动查询', 'promotion:seckill-activity:query', 3, 1, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2061, '秒杀活动创建', 'promotion:seckill-activity:create', 3, 2, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2062, '秒杀活动更新', 'promotion:seckill-activity:update', 3, 3, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2063, '秒杀活动删除', 'promotion:seckill-activity:delete', 3, 4, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2064, '秒杀活动导出', 'promotion:seckill-activity:export', 3, 5, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2066, '秒杀时段管理', '', 2, 0, 2030, 'seckill-time', '', 'mall/promotion/seckill/seckillTime/index', 'PromotionSeckillTime', 0, b'0', b'1', b'1', '', '2022-11-15 19:46:50', '1', '2023-04-08 11:46:17', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2067, '秒杀时段查询', 'promotion:seckill-time:query', 3, 1, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2068, '秒杀时段创建', 'promotion:seckill-time:create', 3, 2, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2069, '秒杀时段更新', 'promotion:seckill-time:update', 3, 3, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2070, '秒杀时段删除', 'promotion:seckill-time:delete', 3, 4, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2071, '秒杀时段导出', 'promotion:seckill-time:export', 3, 5, 2066, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '', '2022-11-15 19:46:51', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2066, '秒杀时段', '', 2, 1, 2209, 'config', 'ep:baseball', 'mall/promotion/seckill/config/index', 'PromotionSeckillConfig', 0, b'1', b'1', b'1', '', '2022-11-15 19:46:50', '1', '2023-06-24 18:57:14', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2067, '秒杀时段查询', 'promotion:seckill-config:query', 3, 1, 2066, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:50:25', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2068, '秒杀时段创建', 'promotion:seckill-config:create', 3, 2, 2066, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:48:39', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2069, '秒杀时段更新', 'promotion:seckill-config:update', 3, 3, 2066, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:50:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2070, '秒杀时段删除', 'promotion:seckill-config:delete', 3, 4, 2066, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:50:32', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2072, '订单中心', '', 1, 65, 0, '/trade', 'order', NULL, NULL, 0, b'1', b'1', b'1', '1', '2022-11-19 18:57:19', '1', '2022-12-10 16:32:57', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2073, '售后退款', '', 2, 1, 2072, 'trade/after-sale', 'education', 'mall/trade/afterSale/index', 'TradeAfterSale', 0, b'1', b'1', b'1', '', '2022-11-19 20:15:32', '1', '2023-04-08 11:43:19', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2074, '售后查询', 'trade:after-sale:query', 3, 1, 2073, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-19 20:15:33', '1', '2022-12-10 21:04:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2075, '秒杀活动关闭', 'promotion:sekill-activity:close', 3, 6, 2059, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-11-28 20:20:15', '1', '2022-11-28 20:20:15', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2076, '订单列表', '', 2, 0, 2072, 'trade/order', 'list', 'mall/trade/order/index', 'TradeOrder', 0, b'1', b'1', b'1', '1', '2022-12-10 21:05:44', '1', '2023-04-08 11:42:23', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2077, '物流公司管理管理', '', 2, 0, 2072, 'express-company', '', 'mall/trade/expressCompany/index', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '1', '2022-12-20 23:36:20', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2078, '物流公司管理查询', 'trade:express-company:query', 3, 1, 2077, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '', '2022-12-20 23:27:55', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2079, '物流公司管理创建', 'trade:express-company:create', 3, 2, 2077, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '', '2022-12-20 23:27:55', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2080, '物流公司管理更新', 'trade:express-company:update', 3, 3, 2077, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '', '2022-12-20 23:27:55', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2081, '物流公司管理删除', 'trade:express-company:delete', 3, 4, 2077, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '', '2022-12-20 23:27:55', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2082, '物流公司管理导出', 'trade:express-company:export', 3, 5, 2077, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-12-20 23:27:55', '', '2022-12-20 23:27:55', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2083, '地区管理', '', 2, 14, 1, 'area', 'row', 'system/area/index', 'SystemArea', 0, b'1', b'1', b'1', '1', '2022-12-23 17:35:05', '1', '2023-04-08 09:01:37', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2084, '公众号管理', '', 1, 100, 0, '/mp', 'wechat', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-01-01 20:11:04', '1', '2023-01-15 11:28:57', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2085, '账号管理', '', 2, 1, 2084, 'account', 'phone', 'mp/account/index', 'MpAccount', 0, b'1', b'1', b'1', '1', '2023-01-01 20:13:31', '1', '2023-02-09 23:56:39', b'0');
@ -2086,6 +1612,47 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2159, 'Boot 开发文档', '', 1, 1, 0, 'https://doc.iocoder.cn/', 'education', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-02-10 22:46:28', '1', '2023-02-10 22:46:28', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2160, 'Cloud 开发文档', '', 1, 2, 0, 'https://cloud.iocoder.cn', 'documentation', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-02-10 22:47:07', '1', '2023-02-10 22:47:07', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2161, '接入示例', '', 2, 99, 1117, 'demo-order', 'drag', 'pay/demo/index', NULL, 0, b'1', b'1', b'1', '', '2023-02-11 14:21:42', '1', '2023-02-11 22:26:35', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2162, '商品导出', 'product:spu:export', 3, 5, 2014, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2164, '配送管理', '', 1, 2, 2072, 'delivery', '', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:18:02', '1', '2023-05-24 23:24:13', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2165, '快递发货', '', 1, 0, 2164, 'express', '', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:22:06', '1', '2023-05-18 09:22:06', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2166, '门店自提', '', 1, 1, 2164, 'pick-up-store', '', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:23:14', '1', '2023-05-18 09:23:14', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2167, '快递公司', '', 2, 0, 2165, 'express', '', 'mall/trade/delivery/express/index', 'Express', 0, b'1', b'1', b'1', '1', '2023-05-18 09:27:21', '1', '2023-05-18 22:11:14', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2168, '快递公司查询', 'trade:delivery:express:query', 3, 1, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2169, '快递公司创建', 'trade:delivery:express:create', 3, 2, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2170, '快递公司更新', 'trade:delivery:express:update', 3, 3, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2171, '快递公司删除', 'trade:delivery:express:delete', 3, 4, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2172, '快递公司导出', 'trade:delivery:express:export', 3, 5, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2173, '运费模版', 'trade:delivery:express-template:query', 2, 1, 2165, 'express-template', '', 'mall/trade/delivery/expressTemplate/index', 'ExpressTemplate', 0, b'1', b'1', b'1', '1', '2023-05-20 06:48:10', '1', '2023-05-20 06:48:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2174, '快递运费模板查询', 'trade:delivery:express-template:query', 3, 1, 2173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2175, '快递运费模板创建', 'trade:delivery:express-template:create', 3, 2, 2173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2176, '快递运费模板更新', 'trade:delivery:express-template:update', 3, 3, 2173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2177, '快递运费模板删除', 'trade:delivery:express-template:delete', 3, 4, 2173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2178, '快递运费模板导出', 'trade:delivery:express-template:export', 3, 5, 2173, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2179, '门店管理', '', 2, 1, 2166, 'pick-up-store', '', 'mall/trade/delivery/pickUpStore/index', 'PickUpStore', 0, b'1', b'1', b'1', '1', '2023-05-25 10:50:00', '1', '2023-05-25 10:50:00', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2180, '自提门店查询', 'trade:delivery:pick-up-store:query', 3, 1, 2179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2181, '自提门店创建', 'trade:delivery:pick-up-store:create', 3, 2, 2179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2182, '自提门店更新', 'trade:delivery:pick-up-store:update', 3, 3, 2179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2183, '自提门店删除', 'trade:delivery:pick-up-store:delete', 3, 4, 2179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2184, '自提门店导出', 'trade:delivery:pick-up-store:export', 3, 5, 2179, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2209, '秒杀活动', '', 2, 3, 2030, 'seckill', 'ep:place', '', '', 0, b'1', b'1', b'1', '1', '2023-06-24 17:39:13', '1', '2023-06-24 18:55:15', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2262, '会员中心', '', 1, 55, 0, '/member', 'date-range', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-06-10 00:42:03', '1', '2023-06-28 22:52:34', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2275, '积分配置', '', 2, 0, 2299, 'config', '', 'member/point/config/index', 'PointConfig', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 22:50:59', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2276, '积分设置查询', 'point:config:query', 3, 1, 2275, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '', '2023-06-10 02:07:44', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2277, '积分设置创建', 'point:config:save', 3, 2, 2275, '', '', '', '', 0, b'1', b'1', b'1', '', '2023-06-10 02:07:44', '1', '2023-06-27 20:32:31', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2281, '签到配置', '', 2, 2, 2300, 'sign-in-config', '', 'member/signin/config/index', 'SignInConfig', 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '1', '2023-07-02 15:04:15', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2282, '积分签到规则查询', 'point:sign-in-config:query', 3, 1, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2283, '积分签到规则创建', 'point:sign-in-config:create', 3, 2, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2284, '积分签到规则更新', 'point:sign-in-config:update', 3, 3, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2285, '积分签到规则删除', 'point:sign-in-config:delete', 3, 4, 2281, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2287, '积分记录', '', 2, 1, 2299, 'record', '', 'member/point/record/index', 'PointRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '1', '2023-06-27 22:51:07', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2288, '用户积分记录查询', 'point:record:query', 3, 1, 2287, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:18:50', '', '2023-06-10 04:18:50', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2293, '签到记录', '', 2, 3, 2300, 'sign-in-record', '', 'member/signin/record/index', 'SignInRecord', 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '1', '2023-07-02 15:04:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2294, '用户签到积分查询', 'point:sign-in-record:query', 3, 1, 2293, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2297, '用户签到积分删除', 'point:sign-in-record:delete', 3, 4, 2293, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2299, '会员积分', '', 1, 1, 2262, 'point', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:48:51', '1', '2023-06-27 22:48:51', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2300, '会员签到', '', 1, 2, 2262, 'signin', '', '', '', 0, b'1', b'1', b'1', '1', '2023-06-27 22:49:53', '1', '2023-06-27 22:49:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2301, '回调通知', '', 2, 4, 1117, 'notify', 'example', 'pay/notify/index', 'PayNotify', 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '1', '2023-07-20 13:45:08', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', b'0');
COMMIT;
-- ----------------------------
@ -2202,7 +1769,7 @@ CREATE TABLE `system_oauth2_access_token` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1785 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
) ENGINE = InnoDB AUTO_INCREMENT = 2231 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
-- ----------------------------
-- Records of system_oauth2_access_token
@ -2324,7 +1891,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 738 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
) ENGINE = InnoDB AUTO_INCREMENT = 804 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
-- ----------------------------
-- Records of system_oauth2_refresh_token
@ -2364,7 +1931,7 @@ CREATE TABLE `system_operate_log` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6440 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
) ENGINE = InnoDB AUTO_INCREMENT = 7134 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
-- ----------------------------
-- Records of system_operate_log
@ -2946,7 +2513,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2062, 2, 1128, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2063, 2, 1129, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2064, 2, 1130, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2065, 2, 1131, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2066, 2, 1132, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2067, 2, 1133, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2068, 2, 1134, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
@ -2974,12 +2540,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2090, 2, 1176, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2091, 2, 1177, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2092, 2, 1178, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2093, 2, 1179, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2094, 2, 1180, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2095, 2, 1181, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2096, 2, 1182, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2097, 2, 1183, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2098, 2, 1184, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2099, 2, 1226, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2100, 2, 1227, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2101, 2, 1228, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
@ -3524,7 +3084,7 @@ CREATE TABLE `system_tenant` (
BEGIN;
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'https://www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2022-02-23 12:15:11', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'http://www.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2022-05-17 10:03:59', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'https://www.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'https://www.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-04-15 09:17:54', b'0');
COMMIT;
-- ----------------------------
@ -3662,7 +3222,7 @@ CREATE TABLE `system_users` (
-- Records of system_users
-- ----------------------------
BEGIN;
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://test.yudao.iocoder.cn/e1fdd7271685ec143a0900681606406621717a666ad0b2798b096df41422b32f.png', 0, '0:0:0:0:0:0:0:1', '2023-04-13 23:09:16', 'admin', '2021-01-05 17:03:47', NULL, '2023-04-13 23:09:16', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://test.yudao.iocoder.cn/e1fdd7271685ec143a0900681606406621717a666ad0b2798b096df41422b32f.png', 0, '127.0.0.1', '2023-07-24 08:41:23', 'admin', '2021-01-05 17:03:47', NULL, '2023-07-24 08:41:23', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '127.0.0.1', '2022-05-28 15:43:17', '', '2021-01-21 02:13:53', NULL, '2022-07-09 09:00:33', b'0', 1);

View File

@ -96,6 +96,11 @@
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-trade</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>

View File

@ -33,7 +33,11 @@ public class ServiceErrorCodeRange {
// 模块 system 错误码区间 [1-002-000-000 ~ 1-003-000-000)
// 模块 report 错误码区间 [1-003-000-000 ~ 1-004-000-000)
// 模块 member 错误码区间 [1-004-000-000 ~ 1-005-000-000)
// 模块 mp 错误码区间 [1-006-000-000 ~ 1-007-000-000)
// 模块 pay 错误码区间 [1-007-000-000 ~ 1-008-000-000)
// 模块 product 错误码区间 [1-008-000-000 ~ 1-009-000-000)
// 模块 bpm 错误码区间 [1-009-000-000 ~ 1-010-000-000)
// 模块 trade 错误码区间 [1-011-000-000 ~ 1-012-000-000)
// 模块 promotion 错误码区间 [1-013-000-000 ~ 1-014-000-000)
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.exception.util;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
@ -80,6 +81,10 @@ public class ServiceExceptionUtil {
return new ServiceException(code, message);
}
public static ServiceException invalidParamException(String messagePattern, Object... params) {
return exception0(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), messagePattern, params);
}
// ========== 格式化方法 ==========
/**

View File

@ -55,7 +55,6 @@ public class DateUtils {
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}
@Deprecated
public static Date addTime(Duration duration) {
return new Date(System.currentTimeMillis() + duration.toMillis());
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@ -13,6 +14,7 @@ import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
@ -29,6 +31,7 @@ public class JsonUtils {
static {
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
}
@ -70,6 +73,18 @@ public class JsonUtils {
}
}
public static <T> T parseObject(String text, Type type) {
if (StrUtil.isEmpty(text)) {
return null;
}
try {
return objectMapper.readValue(text, objectMapper.getTypeFactory().constructType(type));
} catch (IOException e) {
log.error("json parse err,json:{}", text, e);
throw new RuntimeException(e);
}
}
/**
* 将字符串解析成指定类型的对象
* 使用 {@link #parseObject(String, Class)} @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 的场景下

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.spring;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
@ -24,7 +25,13 @@ import java.util.Map;
*/
public class SpringExpressionUtils {
/**
* spel表达式解析器
*/
private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
/**
* 参数名发现器
*/
private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
private SpringExpressionUtils() {
@ -33,7 +40,7 @@ public class SpringExpressionUtils {
/**
* 从切面中单个解析 EL 表达式的结果
*
* @param joinPoint 切面点
* @param joinPoint 切面点
* @param expressionString EL 表达式数组
* @return 执行界面
*/
@ -45,7 +52,7 @@ public class SpringExpressionUtils {
/**
* 从切面中批量解析 EL 表达式的结果
*
* @param joinPoint 切面点
* @param joinPoint 切面点
* @param expressionStrings EL 表达式数组
* @return 结果key 为表达式value 为对应值
*/
@ -79,4 +86,48 @@ public class SpringExpressionUtils {
});
return result;
}
/**
* JoinPoint 切面 批量解析 EL 表达式转换 jspl参数
*
* @param joinPoint 切面点
* @param info 返回值
* @param expressionStrings EL 表达式数组
* @return Map<String, Object> 结果
* @author 陈賝
* @since 2023/6/18 11:20
*/
// TODO @chenchen: 这个方法 parseExpressions 比较接近是不是可以合并下
public static Map<String, Object> parseExpression(JoinPoint joinPoint, Object info, List<String> expressionStrings) {
// 如果为空则不进行解析
if (CollUtil.isEmpty(expressionStrings)) {
return MapUtil.newHashMap();
}
// 第一步构建解析的上下文 EvaluationContext
// 通过 joinPoint 获取被注解方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 使用 spring ParameterNameDiscoverer 获取方法形参名数组
String[] parameterNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method);
// Spring 的表达式上下文对象
EvaluationContext context = new StandardEvaluationContext();
if (ArrayUtil.isNotEmpty(parameterNames)) {
//获取方法参数值
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
// 替换 SP EL 里的变量值为实际值 比如 #user --> user对象
context.setVariable(parameterNames[i], args[i]);
}
context.setVariable("info", info);
}
// 第二步逐个参数解析
Map<String, Object> result = MapUtil.newHashMap(expressionStrings.size(), true);
expressionStrings.forEach(key -> {
Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context);
result.put(key, value);
});
return result;
}
}

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.framework.common.util.string;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
@ -17,14 +16,7 @@ import java.util.stream.Collectors;
public class StrUtils {
public static String maxLength(CharSequence str, int maxLength) {
Assert.isTrue(maxLength > 0);
if (null == str) {
return null;
}
if (str.length() <= maxLength) {
return str.toString();
}
return StrUtil.sub(str, 0, maxLength - 3) + "..."; // -3 的原因是该方法会补充 ... 恰好
return StrUtil.maxLength(str, maxLength - 3); // -3 的原因是该方法会补充 ... 恰好
}
/**
@ -48,12 +40,14 @@ public class StrUtils {
return false;
}
public static List<Long> splitToLong(String value, CharSequence separator) {
public static List<Long> splitToLong(String value, CharSequence separator) {
long[] longs = StrUtil.splitToLong(value, separator);
return Arrays.stream(longs).boxed().collect(Collectors.toList());
}
public static void main(String[] args) {
System.out.println(maxLength("aaaaa", 4));
public static List<Integer> splitToInteger(String value, CharSequence separator) {
int[] integers = StrUtil.splitToInt(value, separator);
return Arrays.stream(integers).boxed().collect(Collectors.toList());
}
}

View File

@ -1,10 +1,12 @@
package cn.iocoder.yudao.framework.common.util.validation;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
import java.util.regex.Pattern;
@ -37,6 +39,12 @@ public class ValidationUtils {
&& PATTERN_XML_NCNAME.matcher(str).matches();
}
public static void validate(Object object, Class<?>... groups) {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Assert.notNull(validator);
validate(validator, object, groups);
}
public static void validate(Validator validator, Object object, Class<?>... groups) {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (CollUtil.isNotEmpty(constraintViolations)) {

View File

@ -48,6 +48,10 @@ public class BannerApplicationRunner implements ApplicationRunner {
if (isNotPresent("cn.iocoder.yudao.module.trade.framework.web.config.TradeWebConfiguration")) {
System.out.println("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
}
// 支付
if (isNotPresent("cn.iocoder.yudao.module.pay.framework.pay.config.PayConfiguration")) {
System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]");
}
});
}

View File

@ -57,6 +57,11 @@ public class DictFrameworkUtils {
log.info("[init][初始化 DictFrameworkUtils 成功]");
}
@SneakyThrows
public static String getDictDataLabel(String dictType, Integer value) {
return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, String.valueOf(value))).getLabel();
}
@SneakyThrows
public static String getDictDataLabel(String dictType, String value) {
return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, value)).getLabel();

View File

@ -37,7 +37,7 @@
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>

View File

@ -1,35 +0,0 @@
package cn.iocoder.yudao.framework.pay.config;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty;
@ConfigurationProperties(prefix = "yudao.pay")
@Validated
@Data
public class PayProperties {
/**
* 回调地址
*
* 实际上对应的 PayNotifyController notifyCallback 方法的 URL
*
* 注意支付渠道统一回调到 payNotifyUrl 地址由支付模块统一处理然后自己的支付模块在回调 PayAppDO.payNotifyUrl 地址
*/
@NotEmpty(message = "回调地址不能为空")
@URL(message = "回调地址的格式必须是 URL")
private String callbackUrl;
/**
* 回跳地址
*
* 实际上对应的 PayNotifyController returnCallback 方法的 URL
*/
@URL(message = "回跳地址的格式必须是 URL")
@NotEmpty(message = "回跳地址不能为空")
private String returnUrl;
}

View File

@ -12,7 +12,6 @@ import org.springframework.context.annotation.Bean;
* @author 芋道源码
*/
@AutoConfiguration
@EnableConfigurationProperties(PayProperties.class)
public class YudaoPayAutoConfiguration {
@Bean

View File

@ -1,12 +1,11 @@
package cn.iocoder.yudao.framework.pay.core.client;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
import java.util.Map;
/**
* 支付客户端用于对接各支付渠道的 SDK实现发起支付退款等功能
@ -22,31 +21,59 @@ public interface PayClient {
*/
Long getId();
// ============ 支付相关 ==========
/**
* 调用支付渠道统一下单
*
* @param reqDTO 下单信息
* @return 各支付渠道的返回结果
* @return 支付订单信息
*/
PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO);
PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO);
/**
* 解析 order 回调数据
*
* @param params HTTP 回调接口 content type application/x-www-form-urlencoded 的所有参数
* @param body HTTP 回调接口的 request body
* @return 支付订单信息
*/
PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body);
/**
* 获得支付订单信息
*
* @param outTradeNo 外部订单号
* @return 支付订单信息
*/
PayOrderRespDTO getOrder(String outTradeNo);
// ============ 退款相关 ==========
/**
* 调用支付渠道进行退款
*
* @param reqDTO 统一退款请求信息
* @return 各支付渠道的统一返回结果
* @return 退款信息
*/
PayRefundUnifiedRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO);
PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO);
/**
* 解析回调数据
* 解析 refund 回调数据
*
* @param rawNotify 通知内容
* @return 回调对象
* 1. {@link PayRefundNotifyRespDTO} 退款通知
* 2. {@link PayOrderNotifyRespDTO} 支付通知
* @param params HTTP 回调接口 content type application/x-www-form-urlencoded 的所有参数
* @param body HTTP 回调接口的 request body
* @return 支付订单信息
*/
default Object parseNotify(PayNotifyReqDTO rawNotify) {
throw new UnsupportedOperationException("未实现 parseNotify 方法!");
}
PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body);
/**
* 获得退款订单信息
*
* @param outTradeNo 外部订单号
* @param outRefundNo 外部退款号
* @return 退款订单信息
*/
PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.pay.core.client;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import javax.validation.ConstraintViolation;
@ -19,24 +20,11 @@ import java.util.Set;
// 2. 反序列化到内存对象时通过 @class 属性可以创建出正确的类型
public interface PayClientConfig {
/**
* 配置验证参数是
*
* @param validator 校验对象
* @return 配置好的验证参数
*/
Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator);
// TODO @aquan貌似抽象一个 validation group 就好了
/**
* 参数校验
*
* @param validator 校验对象
*/
default void validate(Validator validator) {
Set<ConstraintViolation<PayClientConfig>> violations = verifyParam(validator);
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}
void validate(Validator validator);
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.notify;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import java.util.Map;
/**
* 支付订单退款订单回调渠道的统一通知请求数据
*/
@Data
@ToString
@Builder
public class PayNotifyReqDTO {
/**
* HTTP 回调接口的 request body
*/
private String body;
/**
* HTTP 回调接口 content type application/x-www-form-urlencoded 的所有参数
*/
private Map<String,String> params;
}

View File

@ -1,48 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.notify;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 支付通知 Response DTO
*
* @author 芋道源码
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayOrderNotifyRespDTO {
/**
* 支付订单号支付模块的
*/
private String orderExtensionNo;
/**
* 支付渠道编号
*/
private String channelOrderNo;
/**
* 支付渠道用户编号
*/
private String channelUserId;
/**
* 支付成功时间
*/
private LocalDateTime successTime;
/**
* TODO @jason 结合其他的渠道定义成枚举,
*
* alipay
* TRADE_CLOSED,未付款交易超时关闭或支付完成后全额退款
* TRADE_SUCCESS, 交易支付成功
* TRADE_FINISHED 交易结束不可退款
*/
private String tradeStatus;
}

View File

@ -1,58 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.notify;
import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import java.time.LocalDateTime;
/**
* 从渠道返回数据中解析得到的支付退款通知的Notify DTO
*
* @author jason
*/
@Data
@ToString
@Builder
public class PayRefundNotifyRespDTO {
/**
* 支付渠道编号
*/
private String channelOrderNo;
/**
* 交易订单号根据规则生成
* 调用支付渠道时使用该字段作为对接的订单号
* 1. 调用微信支付 https://api.mch.weixin.qq.com/pay/unifiedorder 使用该字段作为 out_trade_no
* 2. 调用支付宝 https://opendocs.alipay.com/apis 使用该字段作为 out_trade_no
* 这里对应 pay_extension 里面的 no
* 例如说P202110132239124200055
*/
private String tradeNo;
/**
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no
* 退款请求号
* 标识一次退款请求需要保证在交易号下唯一如需部分退款则此参数必传
* 针对同一次退款请求如果调用接口失败或异常了重试时需要保证退款请求号不能变更
* 防止该笔交易重复退款支付宝会保证同样的退款请求号多次请求只会退一次
* 退款单请求号根据规则生成
*
* 例如说RR202109181134287570000
*/
private String reqNo;
/**
* 退款是否成功
*/
private PayNotifyRefundStatusEnum status;
/**
* 退款成功时间
*/
private LocalDateTime refundSuccessTime;
}

View File

@ -0,0 +1,141 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.order;
import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 渠道支付订单 Response DTO
*
* @author 芋道源码
*/
@Data
public class PayOrderRespDTO {
/**
* 支付状态
*
* 枚举{@link PayOrderStatusRespEnum}
*/
private Integer status;
/**
* 外部订单号
*
* 对应 PayOrderExtensionDO no 字段
*/
private String outTradeNo;
/**
* 支付渠道编号
*/
private String channelOrderNo;
/**
* 支付渠道用户编号
*/
private String channelUserId;
/**
* 支付成功时间
*/
private LocalDateTime successTime;
/**
* 原始的同步/异步通知结果
*/
private Object rawData;
// ========== 主动发起支付时会返回的字段 ==========
/**
* 展示模式
*
* 枚举 {@link PayOrderDisplayModeEnum}
*/
private String displayMode;
/**
* 展示内容
*/
private String displayContent;
/**
* 调用渠道的错误码
*
* 注意这里返回的是业务异常而是不系统异常
* 如果是系统异常则会抛出 {@link PayException}
*/
private String channelErrorCode;
/**
* 调用渠道报错时错误信息
*/
private String channelErrorMsg;
public PayOrderRespDTO() {
}
/**
* 创建WAITING状态的订单返回
*/
public static PayOrderRespDTO waitingOf(String displayMode, String displayContent,
String outTradeNo, Object rawData) {
PayOrderRespDTO respDTO = new PayOrderRespDTO();
respDTO.status = PayOrderStatusRespEnum.WAITING.getStatus();
respDTO.displayMode = displayMode;
respDTO.displayContent = displayContent;
// 相对通用的字段
respDTO.outTradeNo = outTradeNo;
respDTO.rawData = rawData;
return respDTO;
}
/**
* 创建SUCCESS状态的订单返回
*/
public static PayOrderRespDTO successOf(String channelOrderNo, String channelUserId, LocalDateTime successTime,
String outTradeNo, Object rawData) {
PayOrderRespDTO respDTO = new PayOrderRespDTO();
respDTO.status = PayOrderStatusRespEnum.SUCCESS.getStatus();
respDTO.channelOrderNo = channelOrderNo;
respDTO.channelUserId = channelUserId;
respDTO.successTime = successTime;
// 相对通用的字段
respDTO.outTradeNo = outTradeNo;
respDTO.rawData = rawData;
return respDTO;
}
/**
* 创建指定状态的订单返回适合支付渠道回调时
*/
public static PayOrderRespDTO of(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime,
String outTradeNo, Object rawData) {
PayOrderRespDTO respDTO = new PayOrderRespDTO();
respDTO.status = status;
respDTO.channelOrderNo = channelOrderNo;
respDTO.channelUserId = channelUserId;
respDTO.successTime = successTime;
// 相对通用的字段
respDTO.outTradeNo = outTradeNo;
respDTO.rawData = rawData;
return respDTO;
}
/**
* 创建CLOSED状态的订单返回适合调用支付渠道失败时
*/
public static PayOrderRespDTO closedOf(String channelErrorCode, String channelErrorMsg,
String outTradeNo, Object rawData) {
PayOrderRespDTO respDTO = new PayOrderRespDTO();
respDTO.status = PayOrderStatusRespEnum.CLOSED.getStatus();
respDTO.channelErrorCode = channelErrorCode;
respDTO.channelErrorMsg = channelErrorMsg;
// 相对通用的字段
respDTO.outTradeNo = outTradeNo;
respDTO.rawData = rawData;
return respDTO;
}
}

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.order;
import cn.iocoder.yudao.framework.pay.core.enums.PayDisplayModeEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.URL;
@ -8,7 +8,6 @@ import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.awt.*;
import java.time.LocalDateTime;
import java.util.Map;
@ -29,10 +28,12 @@ public class PayOrderUnifiedReqDTO {
// ========== 商户相关字段 ==========
/**
* 商户订单编号
* 外部订单号
*
* 对应 PayOrderExtensionDO no 字段
*/
@NotEmpty(message = "商户订单编号不能为空")
private String merchantOrderId;
@NotEmpty(message = "外部订单编号不能为空")
private String outTradeNo;
/**
* 商品标题
*/
@ -42,7 +43,6 @@ public class PayOrderUnifiedReqDTO {
/**
* 商品描述信息
*/
@NotEmpty(message = "商品描述信息不能为空")
@Length(max = 128, message = "商品描述信息长度不能超过128")
private String body;
/**
@ -64,7 +64,7 @@ public class PayOrderUnifiedReqDTO {
*/
@NotNull(message = "支付金额不能为空")
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
private Integer amount;
private Integer price;
/**
* 支付过期时间
@ -85,7 +85,7 @@ public class PayOrderUnifiedReqDTO {
*
* 如果不传递则每个支付渠道使用默认的方式
*
* 枚举 {@link PayDisplayModeEnum}
* 枚举 {@link PayOrderDisplayModeEnum}
*/
private String displayMode;

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.order;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 统一下单 Response DTO
*
* @author 芋道源码
*/
@Data
public class PayOrderUnifiedRespDTO {
/**
* 展示模式
*/
private String displayMode;
/**
* 展示内容
*/
private String displayContent;
}

View File

@ -0,0 +1,115 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.refund;
import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 渠道退款订单 Response DTO
*
* @author jason
*/
@Data
public class PayRefundRespDTO {
/**
* 退款状态
*
* 枚举 {@link PayRefundStatusRespEnum}
*/
private Integer status;
/**
* 外部退款号
*
* 对应 PayRefundDO no 字段
*/
private String outRefundNo;
/**
* 渠道退款单号
*
* 对应 PayRefundDO.channelRefundNo 字段
*/
private String channelRefundNo;
/**
* 退款成功时间
*/
private LocalDateTime successTime;
/**
* 原始的异步通知结果
*/
private Object rawData;
/**
* 调用渠道的错误码
*
* 注意这里返回的是业务异常而是不系统异常
* 如果是系统异常则会抛出 {@link PayException}
*/
private String channelErrorCode;
/**
* 调用渠道报错时错误信息
*/
private String channelErrorMsg;
private PayRefundRespDTO() {
}
/**
* 创建WAITING状态的退款返回
*/
public static PayRefundRespDTO waitingOf(String channelRefundNo,
String outRefundNo, Object rawData) {
PayRefundRespDTO respDTO = new PayRefundRespDTO();
respDTO.status = PayRefundStatusRespEnum.WAITING.getStatus();
respDTO.channelRefundNo = channelRefundNo;
// 相对通用的字段
respDTO.outRefundNo = outRefundNo;
respDTO.rawData = rawData;
return respDTO;
}
/**
* 创建SUCCESS状态的退款返回
*/
public static PayRefundRespDTO successOf(String channelRefundNo, LocalDateTime successTime,
String outRefundNo, Object rawData) {
PayRefundRespDTO respDTO = new PayRefundRespDTO();
respDTO.status = PayRefundStatusRespEnum.SUCCESS.getStatus();
respDTO.channelRefundNo = channelRefundNo;
respDTO.successTime = successTime;
// 相对通用的字段
respDTO.outRefundNo = outRefundNo;
respDTO.rawData = rawData;
return respDTO;
}
/**
* 创建FAILURE状态的退款返回
*/
public static PayRefundRespDTO failureOf(String outRefundNo, Object rawData) {
return failureOf(null, null,
outRefundNo, rawData);
}
/**
* 创建FAILURE状态的退款返回
*/
public static PayRefundRespDTO failureOf(String channelErrorCode, String channelErrorMsg,
String outRefundNo, Object rawData) {
PayRefundRespDTO respDTO = new PayRefundRespDTO();
respDTO.status = PayRefundStatusRespEnum.FAILURE.getStatus();
respDTO.channelErrorCode = channelErrorCode;
respDTO.channelErrorMsg = channelErrorMsg;
// 相对通用的字段
respDTO.outRefundNo = outRefundNo;
respDTO.rawData = rawData;
return respDTO;
}
}

View File

@ -24,33 +24,20 @@ import javax.validation.constraints.NotNull;
public class PayRefundUnifiedReqDTO {
/**
* 用户 IP
* 外部订单号
*
* 对应 PayOrderExtensionDO no 字段
*/
private String userIp;
// TODO @jason这个是否为非必传字段呀只需要传递 payTradeNo 字段即可尽可能精简
/**
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 transaction_id
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 trade_no
* 渠道订单号
*/
private String channelOrderNo;
@NotEmpty(message = "外部订单编号不能为空")
private String outTradeNo;
/**
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no
* 支付交易号 {PayOrderExtensionDO no字段} 渠道订单号 不能同时为空
* 外部退款号
*
* 对应 PayRefundDO no 字段
*/
private String payTradeNo;
/**
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no
* https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no
* 退款请求单号 同一退款请求单号多次请求只退一笔
* 使用 商户的退款单号{PayRefundDO 字段 merchantRefundNo}
*/
@NotEmpty(message = "退款请求单号")
private String merchantRefundId;
@NotEmpty(message = "退款请求单号不能为空")
private String outRefundNo;
/**
* 退款原因
@ -58,16 +45,25 @@ public class PayRefundUnifiedReqDTO {
@NotEmpty(message = "退款原因不能为空")
private String reason;
/**
* 支付金额单位
*
* 目前微信支付在退款的时候必须传递该字段
*/
@NotNull(message = "支付金额不能为空")
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
private Integer payPrice;
/**
* 退款金额单位
*/
@NotNull(message = "退款金额不能为空")
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
private Integer amount;
private Integer refundPrice;
/**
* 退款结果 notify 回调地址 支付宝退款不需要回调地址 微信需要
* 退款结果 notify 回调地址
*/
@NotEmpty(message = "支付结果的回调地址不能为空")
@URL(message = "支付结果的 notify 回调地址必须是 URL 格式")
private String notifyUrl;

View File

@ -1,25 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.refund;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 统一退款 Response DTO
*
* @author jason
*/
@Accessors(chain = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class PayRefundUnifiedRespDTO {
/**
* 渠道退款单编号
*/
private String channelRefundId;
}

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.framework.pay.core.client.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 支付系统异常 Exception
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class PayException extends RuntimeException {
public PayException(Throwable cause) {
super(cause);
}
}

View File

@ -1,23 +1,19 @@
package cn.iocoder.yudao.framework.pay.core.client.impl;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
import com.alipay.api.AlipayResponse;import lombok.extern.slf4j.Slf4j;
import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
import lombok.extern.slf4j.Slf4j;
import javax.validation.Validation;
import java.time.LocalDateTime;
import java.util.Map;
import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
import static cn.hutool.core.date.DatePattern.NORM_DATETIME_MS_FORMATTER;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants.PAY_EXCEPTION;
/**
* 支付客户端的抽象类提供模板方法减少子类的冗余代码
@ -34,6 +30,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
/**
* 渠道编码
*/
@SuppressWarnings("FieldCanBeLocal")
private final String channelCode;
/**
* 支付配置
@ -51,7 +48,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
*/
public final void init() {
doInit();
log.info("[init][配置({}) 初始化完成]", config);
log.info("[init][客户端({}) 初始化完成]", getId());
}
/**
@ -64,7 +61,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
if (config.equals(this.config)) {
return;
}
log.info("[refresh][配置({})发生变化,重新初始化]", config);
log.info("[refresh][客户端({})发生变化,重新初始化]", getId());
this.config = config;
// 初始化
this.init();
@ -75,67 +72,122 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
return channelId;
}
// ============ 支付相关 ==========
@Override
public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
// 执行短信发送
PayOrderUnifiedRespDTO result;
public final PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
ValidationUtils.validate(reqDTO);
// 执行统一下单
PayOrderRespDTO resp;
try {
result = doUnifiedOrder(reqDTO);
resp = doUnifiedOrder(reqDTO);
} catch (ServiceException ex) { // 业务异常都是实现类已经翻译所以直接抛出即可
throw ex;
} catch (Throwable ex) {
// 打印异常日志
log.error("[unifiedOrder][request({}) 发起支付失败]", toJsonString(reqDTO), ex);
throw buildException(ex);
}
return result;
}
protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)
throws Throwable;
@Override
public PayRefundUnifiedRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
PayRefundUnifiedRespDTO resp;
try {
resp = doUnifiedRefund(reqDTO);
} catch (Throwable ex) {
// 记录异常日志
log.error("[unifiedRefund][request({}) 发起退款失败]", toJsonString(reqDTO), ex);
throw buildException(ex);
// 系统异常则包装成 PayException 异常抛出
log.error("[unifiedOrder][客户端({}) request({}) 发起支付异常]",
getId(), toJsonString(reqDTO), ex);
throw buildPayException(ex);
}
return resp;
}
protected abstract PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable;
protected abstract PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)
throws Throwable;
@Override
public final PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
try {
return doParseOrderNotify(params, body);
} catch (ServiceException ex) { // 业务异常都是实现类已经翻译所以直接抛出即可
throw ex;
} catch (Throwable ex) {
log.error("[parseOrderNotify][客户端({}) params({}) body({}) 解析失败]",
getId(), params, body, ex);
throw buildPayException(ex);
}
}
protected abstract PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body)
throws Throwable;
@Override
public final PayOrderRespDTO getOrder(String outTradeNo) {
try {
return doGetOrder(outTradeNo);
} catch (ServiceException ex) { // 业务异常都是实现类已经翻译所以直接抛出即可
throw ex;
} catch (Throwable ex) {
log.error("[getOrder][客户端({}) outTradeNo({}) 查询支付单异常]",
getId(), outTradeNo, ex);
throw buildPayException(ex);
}
}
protected abstract PayOrderRespDTO doGetOrder(String outTradeNo)
throws Throwable;
// ============ 退款相关 ==========
@Override
public final PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
ValidationUtils.validate(reqDTO);
// 执行统一退款
PayRefundRespDTO resp;
try {
resp = doUnifiedRefund(reqDTO);
} catch (ServiceException ex) { // 业务异常都是实现类已经翻译所以直接抛出即可
throw ex;
} catch (Throwable ex) {
// 系统异常则包装成 PayException 异常抛出
log.error("[unifiedRefund][客户端({}) request({}) 发起退款异常]",
getId(), toJsonString(reqDTO), ex);
throw buildPayException(ex);
}
return resp;
}
protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable;
@Override
public final PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
try {
return doParseRefundNotify(params, body);
} catch (ServiceException ex) { // 业务异常都是实现类已经翻译所以直接抛出即可
throw ex;
} catch (Throwable ex) {
log.error("[parseRefundNotify][客户端({}) params({}) body({}) 解析失败]",
getId(), params, body, ex);
throw buildPayException(ex);
}
}
protected abstract PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body)
throws Throwable;
@Override
public final PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo) {
try {
return doGetRefund(outTradeNo, outRefundNo);
} catch (ServiceException ex) { // 业务异常都是实现类已经翻译所以直接抛出即可
throw ex;
} catch (Throwable ex) {
log.error("[getRefund][客户端({}) outTradeNo({}) outRefundNo({}) 查询退款单异常]",
getId(), outTradeNo, outRefundNo, ex);
throw buildPayException(ex);
}
}
protected abstract PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo)
throws Throwable;
// ========== 各种工具方法 ==========
private RuntimeException buildException(Throwable ex) {
if (ex instanceof RuntimeException) {
return (RuntimeException) ex;
private PayException buildPayException(Throwable ex) {
if (ex instanceof PayException) {
return (PayException) ex;
}
throw new RuntimeException(ex);
}
protected void validateSuccess(AlipayResponse response) {
if (response.isSuccess()) {
return;
}
throw exception0(PAY_EXCEPTION.getCode(), response.getSubMsg());
}
protected String formatAmount(Integer amount) {
return String.valueOf(amount / 100.0);
}
protected String formatTime(LocalDateTime time) {
// "yyyy-MM-dd HH:mm:ss"
return LocalDateTimeUtil.format(time, NORM_DATETIME_FORMATTER);
}
protected LocalDateTime parseTime(String str) {
// "yyyy-MM-dd HH:mm:ss"
return LocalDateTimeUtil.parse(str, NORM_DATETIME_FORMATTER);
throw new PayException(ex);
}
}

View File

@ -5,11 +5,8 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClient;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.*;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXLitePayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXNativePayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.*;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ConcurrentHashMap;
@ -58,12 +55,14 @@ public class PayClientFactoryImpl implements PayClientFactory {
PayChannelEnum channelEnum = PayChannelEnum.getByCode(channelCode);
Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelEnum));
// 创建客户端
// TODO @芋艿 WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动所以我手动加了两个具体需要你来配
switch (channelEnum) {
case WX_PUB: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
case WX_LITE: return (AbstractPayClient<Config>) new WXLitePayClient(channelId, (WXPayClientConfig) config); //微信小程序请求支付
case WX_APP: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
case WX_NATIVE: return (AbstractPayClient<Config>) new WXNativePayClient(channelId, (WXPayClientConfig) config);
// 微信支付
case WX_PUB: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config);
case WX_LITE: return (AbstractPayClient<Config>) new WxLitePayClient(channelId, (WxPayClientConfig) config);
case WX_APP: return (AbstractPayClient<Config>) new WxAppPayClient(channelId, (WxPayClientConfig) config);
case WX_BAR: return (AbstractPayClient<Config>) new WxBarPayClient(channelId, (WxPayClientConfig) config);
case WX_NATIVE: return (AbstractPayClient<Config>) new WxNativePayClient(channelId, (WxPayClientConfig) config);
// 支付宝支付
case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config);
case ALIPAY_QR: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);
case ALIPAY_APP: return (AbstractPayClient<Config>) new AlipayAppPayClient(channelId, (AlipayPayClientConfig) config);

View File

@ -1,115 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
/**
* 支付宝抽象类 实现支付宝统一的接口如退款
*
* @author jason
*/
@Slf4j
public abstract class AbstractAlipayClient extends AbstractPayClient<AlipayPayClientConfig> {
protected DefaultAlipayClient client;
public AbstractAlipayClient(Long channelId, String channelCode, AlipayPayClientConfig config) {
super(channelId, channelCode, config);
}
@Override
@SneakyThrows
protected void doInit() {
AlipayConfig alipayConfig = new AlipayConfig();
BeanUtil.copyProperties(config, alipayConfig, false);
this.client = new DefaultAlipayClient(alipayConfig);
}
/**
* 支付宝统一的退款接口 alipay.trade.refund
* @param reqDTO 退款请求 request DTO
* @return 退款请求 Response
*/
@Override
protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
AlipayTradeRefundModel model=new AlipayTradeRefundModel();
model.setTradeNo(reqDTO.getChannelOrderNo());
model.setOutTradeNo(reqDTO.getPayTradeNo());
model.setOutRequestNo(reqDTO.getMerchantRefundId());
model.setRefundAmount(formatAmount(reqDTO.getAmount()).toString());
model.setRefundReason(reqDTO.getReason());
AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
refundRequest.setBizModel(model);
refundRequest.setNotifyUrl(reqDTO.getNotifyUrl());
refundRequest.setReturnUrl(reqDTO.getNotifyUrl());
try {
AlipayTradeRefundResponse response = client.execute(refundRequest);
log.info("[doUnifiedRefund][response({}) 发起退款 渠道返回", toJsonString(response));
if (response.isSuccess()) {
//退款导致触发的异步通知是发送到支付接口中设置的notify_url
//支付宝不返回退款单号设置为空
PayRefundUnifiedRespDTO respDTO = new PayRefundUnifiedRespDTO();
respDTO.setChannelRefundId("");
// return PayCommonResult.build(response.getCode(), response.getMsg(), respDTO, codeMapping); TODO
return null;
}
// 失败需要抛出异常
// return PayCommonResult.build(response.getCode(), response.getMsg(), null, codeMapping); TODO
return null;
} catch (AlipayApiException e) {
// TODO 记录异常日志
log.error("[doUnifiedRefund][request({}) 发起退款失败,网络读超时,退款状态未知]", toJsonString(reqDTO), e);
// return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping); TODO
return null;
}
}
@Override
@SneakyThrows
public Object parseNotify(PayNotifyReqDTO rawNotify) {
// 1. 校验回调数据
String body = rawNotify.getBody();
Map<String, String> params = rawNotify.getParams();
Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8);
AlipaySignature.rsaCheckV1(bodyObj, config.getAlipayPublicKey(),
StandardCharsets.UTF_8.name(), "RSA2");
// 2.1 退款的情况
if (bodyObj.containsKey("refund_fee")) {
return PayRefundNotifyRespDTO.builder().channelOrderNo(bodyObj.get("trade_no"))
.tradeNo(bodyObj.get("out_trade_no")).reqNo(bodyObj.get("out_biz_no"))
.status(PayNotifyRefundStatusEnum.SUCCESS)
.refundSuccessTime(parseTime(params.get("gmt_refund")))
.build();
}
// 2.2 支付的情况
return PayOrderNotifyRespDTO.builder().orderExtensionNo(bodyObj.get("out_trade_no"))
.channelOrderNo(bodyObj.get("trade_no")).channelUserId(bodyObj.get("seller_id"))
.tradeStatus(bodyObj.get("trade_status")).successTime(parseTime(params.get("notify_time")))
.build();
}
}

View File

@ -0,0 +1,213 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConfig;
import com.alipay.api.AlipayResponse;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
/**
* 支付宝抽象类实现支付宝统一的接口以及部分实现退款
*
* @author jason
*/
@Slf4j
public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPayClientConfig> {
protected DefaultAlipayClient client;
public AbstractAlipayPayClient(Long channelId, String channelCode, AlipayPayClientConfig config) {
super(channelId, channelCode, config);
}
@Override
@SneakyThrows
protected void doInit() {
AlipayConfig alipayConfig = new AlipayConfig();
BeanUtil.copyProperties(config, alipayConfig, false);
this.client = new DefaultAlipayClient(alipayConfig);
}
// ============ 支付相关 ==========
/**
* 构造支付关闭的 {@link PayOrderRespDTO} 对象
*
* @return 支付关闭的 {@link PayOrderRespDTO} 对象
*/
protected PayOrderRespDTO buildClosedPayOrderRespDTO(PayOrderUnifiedReqDTO reqDTO, AlipayResponse response) {
Assert.isFalse(response.isSuccess());
return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
reqDTO.getOutTradeNo(), response);
}
@Override
public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws Throwable {
// 1. 校验回调数据
Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8);
AlipaySignature.rsaCheckV1(bodyObj, config.getAlipayPublicKey(),
StandardCharsets.UTF_8.name(), config.getSignType());
// 2. 解析订单的状态
// 额外说明支付宝不仅仅支付成功会回调再各种触发支付单数据变化时都会进行回调所以这里 status 的解析会写的比较复杂
Integer status = parseStatus(bodyObj.get("trade_status"));
// 特殊逻辑: 支付宝没有退款成功的状态所以如果有退款金额我们认为是退款成功
if (MapUtil.getDouble(bodyObj, "refund_fee", 0D) > 0) {
status = PayOrderStatusRespEnum.REFUND.getStatus();
}
Assert.notNull(status, (Supplier<Throwable>) () -> {
throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", body));
});
return PayOrderRespDTO.of(status, bodyObj.get("trade_no"), bodyObj.get("seller_id"), parseTime(params.get("gmt_payment")),
bodyObj.get("out_trade_no"), body);
}
@Override
protected PayOrderRespDTO doGetOrder(String outTradeNo) throws Throwable {
// 1.1 构建 AlipayTradeRefundModel 请求
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo(outTradeNo);
// 1.2 构建 AlipayTradeQueryRequest 请求
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizModel(model);
// 2.1 执行请求
AlipayTradeQueryResponse response = client.execute(request);
if (!response.isSuccess()) { // 不成功例如说订单不存在
return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
outTradeNo, response);
}
// 2.2 解析订单的状态
Integer status = parseStatus(response.getTradeStatus());
Assert.notNull(status, (Supplier<Throwable>) () -> {
throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody()));
});
return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()),
outTradeNo, response);
}
private static Integer parseStatus(String tradeStatus) {
return Objects.equals("WAIT_BUYER_PAY", tradeStatus) ? PayOrderStatusRespEnum.WAITING.getStatus()
: ObjectUtils.equalsAny(tradeStatus, "TRADE_FINISHED", "TRADE_SUCCESS") ? PayOrderStatusRespEnum.SUCCESS.getStatus()
: Objects.equals("TRADE_CLOSED", tradeStatus) ? PayOrderStatusRespEnum.CLOSED.getStatus() : null;
}
// ============ 退款相关 ==========
/**
* 支付宝统一的退款接口 alipay.trade.refund
*
* @param reqDTO 退款请求 request DTO
* @return 退款请求 Response
*/
@Override
protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws AlipayApiException {
// 1.1 构建 AlipayTradeRefundModel 请求
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
model.setOutTradeNo(reqDTO.getOutTradeNo());
model.setOutRequestNo(reqDTO.getOutRefundNo());
model.setRefundAmount(formatAmount(reqDTO.getRefundPrice()));
model.setRefundReason(reqDTO.getReason());
// 1.2 构建 AlipayTradePayRequest 请求
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
request.setBizModel(model);
// 2.1 执行请求
AlipayTradeRefundResponse response = client.execute(request);
if (!response.isSuccess()) {
return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
}
// 2.2 创建返回结果
// 支付宝只要退款调用返回 success就认为退款成功不需要回调具体可见 parseNotify 方法的说明
// 另外支付宝没有退款单号所以不用设置
return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
reqDTO.getOutRefundNo(), response);
}
@Override
public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
// 补充说明支付宝退款时没有回调这点和微信支付是不同的并且退款分成部分退款和全部退款
// 部分退款是会有回调但是它回调的是订单状态的同步回调不是退款订单的回调
// 全部退款Wap 支付有订单状态的同步回调但是 PC/扫码又没有
// 所以这里在解析时即使是退款导致的订单状态同步我们也忽略不做为退款同步而是订单的回调
// 实际上支付宝退款只要发起成功就可以认为退款成功不需要等待回调
throw new UnsupportedOperationException("支付宝无退款回调");
}
@Override
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws AlipayApiException {
// 1.1 构建 AlipayTradeFastpayRefundQueryModel 请求
AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
model.setOutTradeNo(outTradeNo);
model.setOutRequestNo(outRefundNo);
model.setQueryOptions(Collections.singletonList("gmt_refund_pay"));
// 1.2 构建 AlipayTradeFastpayRefundQueryRequest 请求
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
request.setBizModel(model);
// 2.1 执行请求
AlipayTradeFastpayRefundQueryResponse response = client.execute(request);
if (!response.isSuccess()) {
// 明确不存在的情况应该就是失败可进行关闭
if (ObjectUtils.equalsAny(response.getSubCode(), "TRADE_NOT_EXIST", "ACQ.TRADE_NOT_EXIST")) {
return PayRefundRespDTO.failureOf(outRefundNo, response);
}
// 可能存在ACQ.SYSTEM_ERROR系统错误等情况所以返回 WAIT 继续等待
return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
}
// 2.2 创建返回结果
if (Objects.equals(response.getRefundStatus(), "REFUND_SUCCESS")) {
return PayRefundRespDTO.successOf(null, LocalDateTimeUtil.of(response.getGmtRefundPay()),
outRefundNo, response);
}
return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
}
// ========== 各种工具方法 ==========
protected String formatAmount(Integer amount) {
return String.valueOf(amount / 100.0);
}
protected String formatTime(LocalDateTime time) {
return LocalDateTimeUtil.format(time, NORM_DATETIME_FORMATTER);
}
protected LocalDateTime parseTime(String str) {
return LocalDateTimeUtil.parse(str, NORM_DATETIME_FORMATTER);
}
}

View File

@ -1,9 +1,9 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.PayDisplayModeEnum;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
@ -20,25 +20,26 @@ import lombok.extern.slf4j.Slf4j;
* @author 芋道源码
*/
@Slf4j
public class AlipayAppPayClient extends AbstractAlipayClient {
public class AlipayAppPayClient extends AbstractAlipayPayClient {
public AlipayAppPayClient(Long channelId, AlipayPayClientConfig config) {
super(channelId, PayChannelEnum.ALIPAY_APP.getCode(), config);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
// 1.1 构建 AlipayTradeAppPayModel 请求
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
// 通用的参数
model.setOutTradeNo(reqDTO.getMerchantOrderId());
model.setOutTradeNo(reqDTO.getOutTradeNo());
model.setSubject(reqDTO.getSubject());
model.setBody(reqDTO.getBody());
model.setTotalAmount(formatAmount(reqDTO.getAmount()));
model.setProductCode(" QUICK_MSECURITY_PAY"); // 销售产品码无线快捷支付产品
model.setBody(reqDTO.getBody() + "test");
model.setTotalAmount(formatAmount(reqDTO.getPrice()));
model.setTimeExpire(formatTime(reqDTO.getExpireTime()));
model.setProductCode("QUICK_MSECURITY_PAY"); // 销售产品码无线快捷支付产品
// 个性化的参数
// 支付宝扫码支付只有一种展示
String displayMode = PayDisplayModeEnum.APP.getMode();
String displayMode = PayOrderDisplayModeEnum.APP.getMode();
// 1.2 构建 AlipayTradePrecreateRequest 请求
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
@ -47,11 +48,13 @@ public class AlipayAppPayClient extends AbstractAlipayClient {
request.setReturnUrl(reqDTO.getReturnUrl());
// 2.1 执行请求
AlipayTradeAppPayResponse response = client.execute(request);
AlipayTradeAppPayResponse response = client.sdkExecute(request);
// 2.2 处理结果
validateSuccess(response);
return new PayOrderUnifiedRespDTO()
.setDisplayMode(displayMode).setDisplayContent("");
if (!response.isSuccess()) {
return buildClosedPayOrderRespDTO(reqDTO, response);
}
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
reqDTO.getOutTradeNo(), response);
}
}

View File

@ -1,11 +1,12 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.PayDisplayModeEnum;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.request.AlipayTradePayRequest;
@ -13,7 +14,6 @@ import com.alipay.api.response.AlipayTradePayResponse;
import lombok.extern.slf4j.Slf4j;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
/**
@ -24,14 +24,14 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
* @author 芋道源码
*/
@Slf4j
public class AlipayBarPayClient extends AbstractAlipayClient {
public class AlipayBarPayClient extends AbstractAlipayPayClient {
public AlipayBarPayClient(Long channelId, AlipayPayClientConfig config) {
super(channelId, PayChannelEnum.ALIPAY_BAR.getCode(), config);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
String authCode = MapUtil.getStr(reqDTO.getChannelExtras(), "auth_code");
if (StrUtil.isEmpty(authCode)) {
throw exception0(BAD_REQUEST.getCode(), "条形码不能为空");
@ -40,15 +40,15 @@ public class AlipayBarPayClient extends AbstractAlipayClient {
// 1.1 构建 AlipayTradePayModel 请求
AlipayTradePayModel model = new AlipayTradePayModel();
// 通用的参数
model.setOutTradeNo(reqDTO.getMerchantOrderId());
model.setOutTradeNo(reqDTO.getOutTradeNo());
model.setSubject(reqDTO.getSubject());
model.setBody(reqDTO.getBody());
model.setTotalAmount(formatAmount(reqDTO.getAmount()));
model.setTotalAmount(formatAmount(reqDTO.getPrice()));
model.setScene("bar_code"); // 当面付条码支付场景
// 个性化的参数
model.setAuthCode(authCode);
// 支付宝条码支付只有一种展示
String displayMode = PayDisplayModeEnum.BAR_CODE.getMode();
String displayMode = PayOrderDisplayModeEnum.BAR_CODE.getMode();
// 1.2 构建 AlipayTradePayRequest 请求
AlipayTradePayRequest request = new AlipayTradePayRequest();
@ -59,8 +59,16 @@ public class AlipayBarPayClient extends AbstractAlipayClient {
// 2.1 执行请求
AlipayTradePayResponse response = client.execute(request);
// 2.2 处理结果
validateSuccess(response);
return new PayOrderUnifiedRespDTO()
.setDisplayMode(displayMode).setDisplayContent("");
if (!response.isSuccess()) {
return buildClosedPayOrderRespDTO(reqDTO, response);
}
if ("10000".equals(response.getCode())) { // 免密支付
return PayOrderRespDTO.successOf(response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getGmtPayment()),
response.getOutTradeNo(), response);
}
// 大额支付需要用户输入密码所以返回 waiting此时前端一般会进行轮询
return PayOrderRespDTO.waitingOf(displayMode, "",
reqDTO.getOutTradeNo(), response);
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import lombok.Data;
@ -9,8 +10,6 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Set;
// TODO 芋艿参数校验
/**
* 支付宝的 PayClientConfig 实现类
* 属性主要来自 {@link com.alipay.api.AlipayConfig} 的必要属性
@ -20,15 +19,6 @@ import java.util.Set;
@Data
public class AlipayPayClientConfig implements PayClientConfig {
/**
* 网关地址 - 线上
*/
public static final String SERVER_URL_PROD = "https://openapi.alipay.com/gateway.do";
/**
* 网关地址 - 沙箱
*/
public static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do";
/**
* 公钥类型 - 公钥模式
*/
@ -45,8 +35,9 @@ public class AlipayPayClientConfig implements PayClientConfig {
/**
* 网关地址
* 1. {@link #SERVER_URL_PROD}
* 2. {@link #SERVER_URL_SANDBOX}
*
* 1. <a href="https://openapi.alipay.com/gateway.do">生产环境</a>
* 2. <a href="https://openapi-sandbox.dl.alipaydev.com/gateway.do">沙箱环境</a>
*/
@NotBlank(message = "网关地址不能为空", groups = {ModePublicKey.class, ModeCertificate.class})
private String serverUrl;
@ -110,8 +101,9 @@ public class AlipayPayClientConfig implements PayClientConfig {
}
@Override
public Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator) {
return validator.validate(this,
public void validate(Validator validator) {
ValidationUtils.validate(validator, this,
MODE_PUBLIC_KEY.equals(this.getMode()) ? ModePublicKey.class : ModeCertificate.class);
}
}

View File

@ -1,12 +1,11 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.Method;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.PayDisplayModeEnum;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
@ -23,29 +22,29 @@ import java.util.Objects;
* @author XGD
*/
@Slf4j
public class AlipayPcPayClient extends AbstractAlipayClient {
public class AlipayPcPayClient extends AbstractAlipayPayClient {
public AlipayPcPayClient(Long channelId, AlipayPayClientConfig config) {
super(channelId, PayChannelEnum.ALIPAY_PC.getCode(), config);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
// 1.1 构建 AlipayTradePagePayModel 请求
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
// 通用的参数
model.setOutTradeNo(reqDTO.getMerchantOrderId());
model.setOutTradeNo(reqDTO.getOutTradeNo());
model.setSubject(reqDTO.getSubject());
model.setBody(reqDTO.getBody());
model.setTotalAmount(formatAmount(reqDTO.getAmount()));
model.setTotalAmount(formatAmount(reqDTO.getPrice()));
model.setTimeExpire(formatTime(reqDTO.getExpireTime()));
model.setProductCode("FAST_INSTANT_TRADE_PAY"); // 销售产品码. 目前 PC 支付场景下仅支持 FAST_INSTANT_TRADE_PAY
// 个性化的参数
// 参考 https://www.pingxx.com/api/支付渠道 extra 参数说明.html alipay_pc_direct 部分
model.setQrPayMode(MapUtil.getStr(reqDTO.getChannelExtras(), "qr_pay_mode"));
model.setQrcodeWidth(MapUtil.getLong(reqDTO.getChannelExtras(), "qr_code_width"));
// 支付宝 PC 支付有多种展示模式因此这里需要计算
String displayMode = getDisplayMode(reqDTO.getDisplayMode(), model.getQrPayMode());
// 如果想弄更多个性化的参数参考 https://www.pingxx.com/api/支付渠道 extra 参数说明.html alipay_pc_direct 部分进行拓展
model.setQrPayMode("2"); // 跳转模式 - 订单码效果参见https://help.pingxx.com/article/1137360/
// 支付宝 PC 支付有两种展示模式FORMURL
String displayMode = ObjectUtil.defaultIfNull(reqDTO.getDisplayMode(),
PayOrderDisplayModeEnum.URL.getMode());
// 1.2 构建 AlipayTradePagePayRequest 请求
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
@ -55,37 +54,17 @@ public class AlipayPcPayClient extends AbstractAlipayClient {
// 2.1 执行请求
AlipayTradePagePayResponse response;
if (Objects.equals(displayMode, PayDisplayModeEnum.FORM.getMode())) {
if (Objects.equals(displayMode, PayOrderDisplayModeEnum.FORM.getMode())) {
response = client.pageExecute(request, Method.POST.name()); // 需要特殊使用 POST 请求
} else {
response = client.pageExecute(request, Method.GET.name());
}
// 2.2 处理结果
validateSuccess(response);
return new PayOrderUnifiedRespDTO().setDisplayMode(displayMode)
.setDisplayContent(response.getBody());
}
/**
* 获得最终的支付 UI 展示模式
*
* @param displayMode 前端传递的 UI 展示模式
* @param qrPayMode 前端传递的二维码模式
* @return 最终的支付 UI 展示模式
*/
private String getDisplayMode(String displayMode, String qrPayMode) {
// 1.1 支付宝二维码的前置模式
if (StrUtil.equalsAny(qrPayMode, "0", "1", "3", "4")) {
return PayDisplayModeEnum.IFRAME.getMode();
if (!response.isSuccess()) {
return buildClosedPayOrderRespDTO(reqDTO, response);
}
// 1.2 支付宝二维码的跳转模式
if (StrUtil.equals(qrPayMode, "2")) {
return PayDisplayModeEnum.URL.getMode();
}
// 2. 前端传递了 UI 展示模式
return displayMode != null ? displayMode :
PayDisplayModeEnum.URL.getMode(); // 模式使用 URL 跳转
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
reqDTO.getOutTradeNo(), response);
}
}

View File

@ -1,9 +1,9 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.PayDisplayModeEnum;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.request.AlipayTradePrecreateRequest;
@ -18,25 +18,25 @@ import lombok.extern.slf4j.Slf4j;
* @author 芋道源码
*/
@Slf4j
public class AlipayQrPayClient extends AbstractAlipayClient {
public class AlipayQrPayClient extends AbstractAlipayPayClient {
public AlipayQrPayClient(Long channelId, AlipayPayClientConfig config) {
super(channelId, PayChannelEnum.ALIPAY_QR.getCode(), config);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
// 1.1 构建 AlipayTradePrecreateModel 请求
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
// 通用的参数
model.setOutTradeNo(reqDTO.getMerchantOrderId());
model.setOutTradeNo(reqDTO.getOutTradeNo());
model.setSubject(reqDTO.getSubject());
model.setBody(reqDTO.getBody());
model.setTotalAmount(formatAmount(reqDTO.getAmount()));
model.setTotalAmount(formatAmount(reqDTO.getPrice()));
model.setProductCode("FACE_TO_FACE_PAYMENT"); // 销售产品码. 目前扫码支付场景下仅支持 FACE_TO_FACE_PAYMENT
// 个性化的参数
// 支付宝扫码支付只有一种展示考虑到前端可能希望二维码扫描后手机打开
String displayMode = PayDisplayModeEnum.QR_CODE.getMode();
String displayMode = PayOrderDisplayModeEnum.QR_CODE.getMode();
// 1.2 构建 AlipayTradePrecreateRequest 请求
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
@ -47,8 +47,11 @@ public class AlipayQrPayClient extends AbstractAlipayClient {
// 2.1 执行请求
AlipayTradePrecreateResponse response = client.execute(request);
// 2.2 处理结果
validateSuccess(response);
return new PayOrderUnifiedRespDTO()
.setDisplayMode(displayMode).setDisplayContent(response.getQrCode());
if (!response.isSuccess()) {
return buildClosedPayOrderRespDTO(reqDTO, response);
}
return PayOrderRespDTO.waitingOf(displayMode, response.getQrCode(),
reqDTO.getOutTradeNo(), response);
}
}

View File

@ -1,11 +1,10 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.Method;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.PayDisplayModeEnum;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
@ -20,26 +19,25 @@ import lombok.extern.slf4j.Slf4j;
* @author 芋道源码
*/
@Slf4j
public class AlipayWapPayClient extends AbstractAlipayClient {
public class AlipayWapPayClient extends AbstractAlipayPayClient {
public AlipayWapPayClient(Long channelId, AlipayPayClientConfig config) {
super(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), config);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException {
// 1.1 构建 AlipayTradeWapPayModel 请求
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
// 通用的参数
model.setOutTradeNo(reqDTO.getMerchantOrderId());
model.setOutTradeNo(reqDTO.getOutTradeNo());
model.setSubject(reqDTO.getSubject());
model.setBody(reqDTO.getBody());
model.setTotalAmount(formatAmount(reqDTO.getAmount()));
model.setTotalAmount(formatAmount(reqDTO.getPrice()));
model.setProductCode("QUICK_WAP_PAY"); // 销售产品码. 目前 Wap 支付场景下仅支持 QUICK_WAP_PAY
// 个性化的参数
// 支付宝 Wap 支付只有一种展示考虑到前端可能希望二维码扫描后手机打开
String displayMode = ObjectUtil.defaultIfNull(reqDTO.getDisplayMode(),
PayDisplayModeEnum.URL.getMode());
// 支付宝 Wap 支付只有一种展示URL
String displayMode = PayOrderDisplayModeEnum.URL.getMode();
// 1.2 构建 AlipayTradeWapPayRequest 请求
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
@ -50,11 +48,12 @@ public class AlipayWapPayClient extends AbstractAlipayClient {
// 2.1 执行请求
AlipayTradeWapPayResponse response = client.pageExecute(request, Method.GET.name());
// 2.2 处理结果
validateSuccess(response);
return new PayOrderUnifiedRespDTO()
.setDisplayMode(displayMode).setDisplayContent(response.getBody());
if (!response.isSuccess()) {
return buildClosedPayOrderRespDTO(reqDTO, response);
}
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
reqDTO.getOutTradeNo(), response);
}
}

View File

@ -0,0 +1,470 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map;
import java.util.Objects;
import static cn.hutool.core.date.DatePattern.*;
import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig.API_VERSION_V2;
/**
* 微信支付抽象类实现微信统一的接口以及部分实现退款
*
* @author 遇到源码
*/
@Slf4j
public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientConfig> {
protected WxPayService client;
public AbstractWxPayClient(Long channelId, String channelCode, WxPayClientConfig config) {
super(channelId, channelCode, config);
}
/**
* 初始化 client 客户端
*
* @param tradeType 交易类型
*/
protected void doInit(String tradeType) {
// 创建 config 配置
WxPayConfig payConfig = new WxPayConfig();
BeanUtil.copyProperties(config, payConfig, "keyContent");
payConfig.setTradeType(tradeType);
// weixin-pay-java 无法设置内容只允许读取文件所以这里要创建临时文件来解决
if (Base64.isBase64(config.getKeyContent())) {
payConfig.setKeyPath(FileUtils.createTempFile(Base64.decode(config.getKeyContent())).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) {
payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateCertContent())) {
payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath());
}
// 创建 client 客户端
client = new WxPayServiceImpl();
client.setConfig(payConfig);
}
// ============ 支付相关 ==========
@Override
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception {
try {
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doUnifiedOrderV2(reqDTO);
case WxPayClientConfig.API_VERSION_V3:
return doUnifiedOrderV3(reqDTO);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
} catch (WxPayException e) {
String errorCode = getErrorCode(e);
String errorMessage = getErrorMessage(e);
return PayOrderRespDTO.closedOf(errorCode, errorMessage,
reqDTO.getOutTradeNo(), e.getXmlString());
}
}
/**
* V2调用支付渠道统一下单
*
* @param reqDTO 下单信息
* @return 各支付渠道的返回结果
*/
protected abstract PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO)
throws Exception;
/**
* V3调用支付渠道统一下单
*
* @param reqDTO 下单信息
* @return 各支付渠道的返回结果
*/
protected abstract PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO)
throws WxPayException;
/**
* V2创建微信下单请求
*
* @param reqDTO 下信息
* @return 下单请求
*/
protected WxPayUnifiedOrderRequest buildPayUnifiedOrderRequestV2(PayOrderUnifiedReqDTO reqDTO) {
return WxPayUnifiedOrderRequest.newBuilder()
.outTradeNo(reqDTO.getOutTradeNo())
.body(reqDTO.getSubject())
.detail(reqDTO.getBody())
.totalFee(reqDTO.getPrice()) // 单位分
.timeExpire(formatDateV2(reqDTO.getExpireTime()))
.spbillCreateIp(reqDTO.getUserIp())
.notifyUrl(reqDTO.getNotifyUrl())
.build();
}
/**
* V3创建微信下单请求
*
* @param reqDTO 下信息
* @return 下单请求
*/
protected WxPayUnifiedOrderV3Request buildPayUnifiedOrderRequestV3(PayOrderUnifiedReqDTO reqDTO) {
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
request.setOutTradeNo(reqDTO.getOutTradeNo());
request.setDescription(reqDTO.getSubject());
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())); // 单位分
request.setTimeExpire(formatDateV3(reqDTO.getExpireTime()));
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
request.setNotifyUrl(reqDTO.getNotifyUrl());
return request;
}
@Override
public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws WxPayException {
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doParseOrderNotifyV2(body);
case WxPayClientConfig.API_VERSION_V3:
return doParseOrderNotifyV3(body);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayOrderRespDTO doParseOrderNotifyV2(String body) throws WxPayException {
// 1. 解析回调
WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body);
// 2. 构建结果
// V2 微信支付的回调只有 SUCCESS 支付成功CLOSED 支付失败两种情况无需像支付宝一样解析的比较复杂
Integer status = Objects.equals(response.getResultCode(), "SUCCESS") ?
PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus();
return PayOrderRespDTO.of(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
response.getOutTradeNo(), body);
}
private PayOrderRespDTO doParseOrderNotifyV3(String body) throws WxPayException {
// 1. 解析回调
WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null);
WxPayOrderNotifyV3Result.DecryptNotifyResult result = response.getResult();
// 2. 构建结果
Integer status = parseStatus(result.getTradeState());
String openid = result.getPayer() != null ? result.getPayer().getOpenid() : null;
return PayOrderRespDTO.of(status, result.getTransactionId(), openid, parseDateV3(result.getSuccessTime()),
result.getOutTradeNo(), body);
}
@Override
protected PayOrderRespDTO doGetOrder(String outTradeNo) throws Throwable {
try {
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doGetOrderV2(outTradeNo);
case WxPayClientConfig.API_VERSION_V3:
return doGetOrderV3(outTradeNo);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
} catch (WxPayException e) {
if (ObjectUtils.equalsAny(e.getErrCode(), "ORDERNOTEXIST", "ORDER_NOT_EXIST")) {
String errorCode = getErrorCode(e);
String errorMessage = getErrorMessage(e);
return PayOrderRespDTO.closedOf(errorCode, errorMessage,
outTradeNo, e.getXmlString());
}
throw e;
}
}
private PayOrderRespDTO doGetOrderV2(String outTradeNo) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayOrderQueryRequest request = WxPayOrderQueryRequest.newBuilder()
.outTradeNo(outTradeNo).build();
// 执行请求
WxPayOrderQueryResult response = client.queryOrder(request);
// 转换结果
Integer status = parseStatus(response.getTradeState());
return PayOrderRespDTO.of(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
outTradeNo, response);
}
private PayOrderRespDTO doGetOrderV3(String outTradeNo) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayOrderQueryV3Request request = new WxPayOrderQueryV3Request()
.setOutTradeNo(outTradeNo);
// 执行请求
WxPayOrderQueryV3Result response = client.queryOrderV3(request);
// 转换结果
Integer status = parseStatus(response.getTradeState());
String openid = response.getPayer() != null ? response.getPayer().getOpenid() : null;
return PayOrderRespDTO.of(status, response.getTransactionId(), openid, parseDateV3(response.getSuccessTime()),
outTradeNo, response);
}
private static Integer parseStatus(String tradeState) {
switch (tradeState) {
case "NOTPAY":
case "USERPAYING": // 支付中等待用户输入密码条码支付独有
return PayOrderStatusRespEnum.WAITING.getStatus();
case "SUCCESS":
return PayOrderStatusRespEnum.SUCCESS.getStatus();
case "REFUND":
return PayOrderStatusRespEnum.REFUND.getStatus();
case "CLOSED":
case "REVOKED": // 已撤销刷卡支付独有
case "PAYERROR": // 支付失败其它原因如银行返回失败
return PayOrderStatusRespEnum.CLOSED.getStatus();
default:
throw new IllegalArgumentException(StrUtil.format("未知的支付状态({})", tradeState));
}
}
// ============ 退款相关 ==========
@Override
protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
try {
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doUnifiedRefundV2(reqDTO);
case WxPayClientConfig.API_VERSION_V3:
return doUnifiedRefundV3(reqDTO);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
} catch (WxPayException e) {
String errorCode = getErrorCode(e);
String errorMessage = getErrorMessage(e);
return PayRefundRespDTO.failureOf(errorCode, errorMessage,
reqDTO.getOutTradeNo(), e.getXmlString());
}
}
private PayRefundRespDTO doUnifiedRefundV2(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
// 1. 构建 WxPayRefundRequest 请求
WxPayRefundRequest request = new WxPayRefundRequest()
.setOutTradeNo(reqDTO.getOutTradeNo())
.setOutRefundNo(reqDTO.getOutRefundNo())
.setRefundFee(reqDTO.getRefundPrice())
.setRefundDesc(reqDTO.getReason())
.setTotalFee(reqDTO.getPayPrice())
.setNotifyUrl(reqDTO.getNotifyUrl());
// 2.1 执行请求
WxPayRefundResult response = client.refundV2(request);
// 2.2 创建返回结果
if (Objects.equals("SUCCESS", response.getResultCode())) { // V2 情况下不直接返回退款成功而是等待异步通知
return PayRefundRespDTO.waitingOf(response.getRefundId(),
reqDTO.getOutRefundNo(), response);
}
return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
}
private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
// 1. 构建 WxPayRefundRequest 请求
WxPayRefundV3Request request = new WxPayRefundV3Request()
.setOutTradeNo(reqDTO.getOutTradeNo())
.setOutRefundNo(reqDTO.getOutRefundNo())
.setAmount(new WxPayRefundV3Request.Amount().setRefund(reqDTO.getRefundPrice())
.setTotal(reqDTO.getPayPrice()).setCurrency("CNY"))
.setReason(reqDTO.getReason())
.setNotifyUrl(reqDTO.getNotifyUrl());
// 2.1 执行请求
WxPayRefundV3Result response = client.refundV3(request);
// 2.2 创建返回结果
if (Objects.equals("SUCCESS", response.getStatus())) {
return PayRefundRespDTO.successOf(response.getRefundId(), parseDateV3(response.getSuccessTime()),
reqDTO.getOutRefundNo(), response);
}
if (Objects.equals("PROCESSING", response.getStatus())) {
return PayRefundRespDTO.waitingOf(response.getRefundId(),
reqDTO.getOutRefundNo(), response);
}
return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
}
@Override
public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) throws WxPayException {
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doParseRefundNotifyV2(body);
case WxPayClientConfig.API_VERSION_V3:
return parseRefundNotifyV3(body);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayRefundRespDTO doParseRefundNotifyV2(String body) throws WxPayException {
// 1. 解析回调
WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body);
WxPayRefundNotifyResult.ReqInfo result = response.getReqInfo();
// 2. 构建结果
if (Objects.equals("SUCCESS", result.getRefundStatus())) {
return PayRefundRespDTO.successOf(result.getRefundId(), parseDateV2B(result.getSuccessTime()),
result.getOutRefundNo(), response);
}
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
}
private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException {
// 1. 解析回调
WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, null);
WxPayRefundNotifyV3Result.DecryptNotifyResult result = response.getResult();
// 2. 构建结果
if (Objects.equals("SUCCESS", result.getRefundStatus())) {
return PayRefundRespDTO.successOf(result.getRefundId(), parseDateV3(result.getSuccessTime()),
result.getOutRefundNo(), response);
}
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
}
@Override
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws WxPayException {
try {
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doGetRefundV2(outTradeNo, outRefundNo);
case WxPayClientConfig.API_VERSION_V3:
return doGetRefundV3(outTradeNo, outRefundNo);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
} catch (WxPayException e) {
if (ObjectUtils.equalsAny(e.getErrCode(), "REFUNDNOTEXIST", "RESOURCE_NOT_EXISTS")) {
String errorCode = getErrorCode(e);
String errorMessage = getErrorMessage(e);
return PayRefundRespDTO.failureOf(errorCode, errorMessage,
outRefundNo, e.getXmlString());
}
throw e;
}
}
private PayRefundRespDTO doGetRefundV2(String outTradeNo, String outRefundNo) throws WxPayException {
// 1. 构建 WxPayRefundRequest 请求
WxPayRefundQueryRequest request = WxPayRefundQueryRequest.newBuilder()
.outTradeNo(outTradeNo)
.outRefundNo(outRefundNo)
.build();
// 2.1 执行请求
WxPayRefundQueryResult response = client.refundQuery(request);
// 2.2 创建返回结果
if (!Objects.equals("SUCCESS", response.getResultCode())) {
return PayRefundRespDTO.waitingOf(null,
outRefundNo, response);
}
WxPayRefundQueryResult.RefundRecord refund = CollUtil.findOne(response.getRefundRecords(),
record -> record.getOutRefundNo().equals(outRefundNo));
if (refund == null) {
return PayRefundRespDTO.failureOf(outRefundNo, response);
}
switch (refund.getRefundStatus()) {
case "SUCCESS":
return PayRefundRespDTO.successOf(refund.getRefundId(), parseDateV2B(refund.getRefundSuccessTime()),
outRefundNo, response);
case "PROCESSING":
return PayRefundRespDTO.waitingOf(refund.getRefundId(),
outRefundNo, response);
case "CHANGE": // 退款到银行发现用户的卡作废或者冻结了导致原路退款银行卡失败资金回流到商户的现金帐号需要商户人工干预通过线下或者财付通转账的方式进行退款
case "FAIL":
return PayRefundRespDTO.failureOf(outRefundNo, response);
default:
throw new IllegalArgumentException(String.format("未知的退款状态(%s)", refund.getRefundStatus()));
}
}
private PayRefundRespDTO doGetRefundV3(String outTradeNo, String outRefundNo) throws WxPayException {
// 1. 构建 WxPayRefundRequest 请求
WxPayRefundQueryV3Request request = new WxPayRefundQueryV3Request();
request.setOutRefundNo(outRefundNo);
// 2.1 执行请求
WxPayRefundQueryV3Result response = client.refundQueryV3(request);
// 2.2 创建返回结果
switch (response.getStatus()) {
case "SUCCESS":
return PayRefundRespDTO.successOf(response.getRefundId(), parseDateV3(response.getSuccessTime()),
outRefundNo, response);
case "PROCESSING":
return PayRefundRespDTO.waitingOf(response.getRefundId(),
outRefundNo, response);
case "ABNORMAL": // 退款异常
case "CLOSED":
return PayRefundRespDTO.failureOf(outRefundNo, response);
default:
throw new IllegalArgumentException(String.format("未知的退款状态(%s)", response.getStatus()));
}
}
// ========== 各种工具方法 ==========
static String formatDateV2(LocalDateTime time) {
return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), PURE_DATETIME_PATTERN);
}
static LocalDateTime parseDateV2(String time) {
return LocalDateTimeUtil.parse(time, PURE_DATETIME_PATTERN);
}
static LocalDateTime parseDateV2B(String time) {
return LocalDateTimeUtil.parse(time, NORM_DATETIME_PATTERN);
}
static String formatDateV3(LocalDateTime time) {
return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), UTC_WITH_XXX_OFFSET_PATTERN);
}
static LocalDateTime parseDateV3(String time) {
return LocalDateTimeUtil.parse(time, UTC_WITH_XXX_OFFSET_PATTERN);
}
static String getErrorCode(WxPayException e) {
if (StrUtil.isNotEmpty(e.getErrCode())) {
return e.getErrCode();
}
if (StrUtil.isNotEmpty(e.getCustomErrorMsg())) {
return "CUSTOM_ERROR";
}
return e.getReturnCode();
}
static String getErrorMessage(WxPayException e) {
if (StrUtil.isNotEmpty(e.getErrCode())) {
return e.getErrCodeDes();
}
if (StrUtil.isNotEmpty(e.getCustomErrorMsg())) {
return e.getCustomErrorMsg();
}
return e.getReturnMsg();
}
}

View File

@ -0,0 +1,63 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import lombok.extern.slf4j.Slf4j;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
/**
* 微信支付App 支付 PayClient 实现类
*
* 文档<a href="https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_5_3.shtml">App 支付</a>
*
* // TODO 芋艿未详细测试因为手头没 App
*
* @author 芋道源码
*/
@Slf4j
public class WxAppPayClient extends AbstractWxPayClient {
public WxAppPayClient(Long channelId, WxPayClientConfig config) {
super(channelId, PayChannelEnum.WX_APP.getCode(), config);
}
@Override
protected void doInit() {
super.doInit(WxPayConstants.TradeType.APP);
}
@Override
protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO);
// 执行请求
WxPayMpOrderResult response = client.createOrder(request);
// 转换结果
return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response),
reqDTO.getOutTradeNo(), response);
}
@Override
protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderV3Request 对象
WxPayUnifiedOrderV3Request request = buildPayUnifiedOrderRequestV3(reqDTO);
// 执行请求
WxPayUnifiedOrderV3Result.JsapiResult response = client.createOrderV3(TradeTypeEnum.APP, request);
// 转换结果
return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response),
reqDTO.getOutTradeNo(), response);
}
}

View File

@ -0,0 +1,107 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
/**
* 微信支付付款码支付 PayClient 实现类
*
* 文档<a href="https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1">付款码支付</a>
*
* @author 芋道源码
*/
@Slf4j
public class WxBarPayClient extends AbstractWxPayClient {
/**
* 微信付款码的过期时间
*/
private static final Duration AUTH_CODE_EXPIRE = Duration.ofMinutes(3);
public WxBarPayClient(Long channelId, WxPayClientConfig config) {
super(channelId, PayChannelEnum.WX_BAR.getCode(), config);
}
@Override
protected void doInit() {
super.doInit(WxPayConstants.TradeType.MICROPAY);
}
@Override
protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 由于付款码需要不断轮询所以需要在较短的时间完成支付
LocalDateTime expireTime = LocalDateTimeUtils.addTime(AUTH_CODE_EXPIRE);
if (expireTime.isAfter(reqDTO.getExpireTime())) {
expireTime = reqDTO.getExpireTime();
}
// 构建 WxPayMicropayRequest 对象
WxPayMicropayRequest request = WxPayMicropayRequest.newBuilder()
.outTradeNo(reqDTO.getOutTradeNo())
.body(reqDTO.getSubject())
.detail(reqDTO.getBody())
.totalFee(reqDTO.getPrice()) // 单位分
.timeExpire(formatDateV2(expireTime))
.spbillCreateIp(reqDTO.getUserIp())
.authCode(getAuthCode(reqDTO))
.build();
// 执行请求重试直到失败过期或者成功
WxPayException lastWxPayException = null;
for (int i = 1; i < Byte.MAX_VALUE; i++) {
try {
WxPayMicropayResult response = client.micropay(request);
// 支付成功例如说1用户输入了密码2用户免密支付
return PayOrderRespDTO.successOf(response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
response.getOutTradeNo(), response)
.setDisplayMode(PayOrderDisplayModeEnum.BAR_CODE.getMode());
} catch (WxPayException ex) {
lastWxPayException = ex;
// 如果不满足这 3 种任一的则直接抛出 WxPayException 异常不仅需处理
// 1. SYSTEMERROR接口返回错误请立即调用被扫订单结果查询API查询当前订单状态并根据订单的状态决定下一步的操作
// 2. USERPAYING用户支付中需要输入密码等待 5 然后调用被扫订单结果查询 API查询当前订单的不同状态决定下一步的操作
// 3. BANKERROR银行系统异常请立即调用被扫订单结果查询 API查询当前订单的不同状态决定下一步的操作
if (!StrUtil.equalsAny(ex.getErrCode(), "SYSTEMERROR", "USERPAYING", "BANKERROR")) {
throw ex;
}
// 等待 5 继续下一轮重新发起支付
log.info("[doUnifiedOrderV2][发起微信 Bar 支付第({})失败,等待下一轮重试,请求({}),响应({})]", i,
toJsonString(request), ex.getMessage());
ThreadUtil.sleep(5, TimeUnit.SECONDS);
}
}
throw lastWxPayException;
}
@Override
protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
return doUnifiedOrderV2(reqDTO);
}
// ========== 各种工具方法 ==========
static String getAuthCode(PayOrderUnifiedReqDTO reqDTO) {
String authCode = MapUtil.getStr(reqDTO.getChannelExtras(), "authCode");
if (StrUtil.isEmpty(authCode)) {
throw invalidParamException("支付请求的 authCode 不能为空!");
}
return authCode;
}
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import lombok.extern.slf4j.Slf4j;
/**
* 微信支付小程序 PayClient 实现类
*
* 由于公众号和小程序的微信支付逻辑一致所以直接进行继承
*
* 文档<a href="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml">JSAPI 下单</>
*
* @author zwy
*/
@Slf4j
public class WxLitePayClient extends WxPubPayClient {
public WxLitePayClient(Long channelId, WxPayClientConfig config) {
super(channelId, PayChannelEnum.WX_LITE.getCode(), config);
}
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import lombok.extern.slf4j.Slf4j;
/**
* 微信支付Native 二维码 PayClient 实现类
*
* 文档<a href="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml">Native 下单</a>
*
* @author zwy
*/
@Slf4j
public class WxNativePayClient extends AbstractWxPayClient {
public WxNativePayClient(Long channelId, WxPayClientConfig config) {
super(channelId, PayChannelEnum.WX_NATIVE.getCode(), config);
}
@Override
protected void doInit() {
super.doInit(WxPayConstants.TradeType.NATIVE);
}
@Override
protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO);
// 执行请求
WxPayNativeOrderResult response = client.createOrder(request);
// 转换结果
return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.QR_CODE.getMode(), response.getCodeUrl(),
reqDTO.getOutTradeNo(), response);
}
@Override
protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderV3Request 对象
WxPayUnifiedOrderV3Request request = buildPayUnifiedOrderRequestV3(reqDTO);
// 执行请求
String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
// 转换结果
return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.QR_CODE.getMode(), response,
reqDTO.getOutTradeNo(), response);
}
}

View File

@ -1,15 +1,14 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import lombok.Data;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.NotBlank;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Set;
/**
* 微信支付的 PayClientConfig 实现类
@ -18,33 +17,37 @@ import java.util.Set;
* @author 芋道源码
*/
@Data
public class WXPayClientConfig implements PayClientConfig {
public class WxPayClientConfig implements PayClientConfig {
/**
* API 版本 - V2
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1
*
* <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1">V2 协议说明</a>
*/
public static final String API_VERSION_V2 = "v2";
/**
* API 版本 - V3
* https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml
*
* <a href="https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml">V3 协议说明</a>
*/
public static final String API_VERSION_V3 = "v3";
/**
* 公众号或者小程序的 appid
*
* 只有公众号或小程序需要该字段
*/
@NotBlank(message = "APPID 不能为空", groups = {V2.class, V3.class})
private String appId;
/**
* 商户号
*/
@NotBlank(message = "商户号 不能为空", groups = {V2.class, V3.class})
@NotBlank(message = "商户号不能为空", groups = {V2.class, V3.class})
private String mchId;
/**
* API 版本
*/
@NotBlank(message = "API 版本 不能为空", groups = {V2.class, V3.class})
@NotBlank(message = "API 版本不能为空", groups = {V2.class, V3.class})
private String apiVersion;
// ========== V2 版本的参数 ==========
@ -52,36 +55,31 @@ public class WXPayClientConfig implements PayClientConfig {
/**
* 商户密钥
*/
@NotBlank(message = "商户密钥 不能为空", groups = V2.class)
@NotBlank(message = "商户密钥不能为空", groups = V2.class)
private String mchKey;
/**
* apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径.
* 对应的字符串
* apiclient_cert.p12 证书文件的对应字符串base64 格式
*
* 注意可通过 {@link #main(String[])} 读取
* 为什么采用 base64 格式因为 p12 读取后是二进制需要转换成 base64 格式才好传输和存储
*/
/// private String keyContent;
@NotBlank(message = "apiclient_cert.p12 不能为空", groups = V2.class)
private String keyContent;
// ========== V3 版本的参数 ==========
/**
* apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径.
* 对应的字符串
* 注意可通过 {@link #main(String[])} 读取
* apiclient_key.pem 证书文件的对应字符串
*/
@NotBlank(message = "apiclient_key 不能为空", groups = V3.class)
private String privateKeyContent;
/**
* apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径.
* 对应的字符串
* <p>
* 注意可通过 {@link #main(String[])} 读取
* apiclient_cert.pem 证书文件的对应的字符串
*/
@NotBlank(message = "apiclient_cert 不能为空", groups = V3.class)
private String privateCertContent;
/**
* apiV3 密钥值
*/
@NotBlank(message = "apiV3 密钥值 不能为空", groups = V3.class)
@NotBlank(message = "apiV3 密钥值不能为空", groups = V3.class)
private String apiV3Key;
/**
@ -97,8 +95,9 @@ public class WXPayClientConfig implements PayClientConfig {
}
@Override
public Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator) {
return validator.validate(this, this.getApiVersion().equals(API_VERSION_V2) ? V2.class : V3.class);
public void validate(Validator validator) {
ValidationUtils.validate(validator, this,
API_VERSION_V2.equals(this.getApiVersion()) ? V2.class : V3.class);
}
public static void main(String[] args) throws FileNotFoundException {

View File

@ -0,0 +1,80 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import lombok.extern.slf4j.Slf4j;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
/**
* 微信支付公众号 PayClient 实现类
*
* 文档<a href="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml">JSAPI 下单</>
*
* @author 芋道源码
*/
@Slf4j
public class WxPubPayClient extends AbstractWxPayClient {
public WxPubPayClient(Long channelId, WxPayClientConfig config) {
super(channelId, PayChannelEnum.WX_PUB.getCode(), config);
}
protected WxPubPayClient(Long channelId, String channelCode, WxPayClientConfig config) {
super(channelId, channelCode, config);
}
@Override
protected void doInit() {
super.doInit(WxPayConstants.TradeType.JSAPI);
}
@Override
protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO)
.setOpenid(getOpenid(reqDTO));
// 执行请求
WxPayMpOrderResult response = client.createOrder(request);
// 转换结果
return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response),
reqDTO.getOutTradeNo(), response);
}
@Override
protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderV3Request request = buildPayUnifiedOrderRequestV3(reqDTO)
.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
// 执行请求
WxPayUnifiedOrderV3Result.JsapiResult response = client.createOrderV3(TradeTypeEnum.JSAPI, request);
// 转换结果
return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response),
reqDTO.getOutTradeNo(), response);
}
// ========== 各种工具方法 ==========
static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {
String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid");
if (StrUtil.isEmpty(openid)) {
throw invalidParamException("支付请求的 openid 不能为空!");
}
return openid;
}
}

View File

@ -1,198 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import java.time.ZoneId;
import java.util.Date;
import java.util.Objects;
/**
* 微信小程序下支付
*
* @author zwy
*/
@Slf4j
public class WXLitePayClient extends AbstractPayClient<WXPayClientConfig> {
private WxPayService client;
public WXLitePayClient(Long channelId, WXPayClientConfig config) {
super(channelId, PayChannelEnum.WX_LITE.getCode(), config);
}
@Override
protected void doInit() {
WxPayConfig payConfig = new WxPayConfig();
BeanUtil.copyProperties(config, payConfig, "privateKeyContent","privateCertContent");
payConfig.setTradeType(WxPayConstants.TradeType.JSAPI); // 设置使用 JS API 支付方式
// if (StrUtil.isNotEmpty(config.getKeyContent())) {
// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8));
// }
if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateCertContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath());
}
// 真实客户端
this.client = new WxPayServiceImpl();
client.setConfig(payConfig);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
throw new UnsupportedOperationException();
// WxPayMpOrderResult response;
// try {
// switch (config.getApiVersion()) {
// case WXPayClientConfig.API_VERSION_V2:
// response = this.unifiedOrderV2(reqDTO);
// break;
// case WXPayClientConfig.API_VERSION_V3:
// WxPayUnifiedOrderV3Result.JsapiResult responseV3 = this.unifiedOrderV3(reqDTO);
// // V3 的结果统一转换成 V2返回的字段是一致的
// response = new WxPayMpOrderResult();
// BeanUtil.copyProperties(responseV3, response, true);
// break;
// default:
// throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
// }
// } catch (WxPayException e) {
// log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e);
// return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"),
// ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()), null, codeMapping);
// }
// return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping);
}
private WxPayMpOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
.outTradeNo(reqDTO.getMerchantOrderId())
.body(reqDTO.getBody())
.totalFee(reqDTO.getAmount().intValue()) // 单位分
.timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss")) // v2的时间格式
.spbillCreateIp(reqDTO.getUserIp())
.openid(getOpenid(reqDTO))
.notifyUrl(reqDTO.getNotifyUrl())
.build();
// 执行请求
return client.createOrder(request);
}
private WxPayUnifiedOrderV3Result.JsapiResult unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
request.setOutTradeNo(reqDTO.getMerchantOrderId());
request.setDescription(reqDTO.getBody());
request.setAmount(new WxPayUnifiedOrderV3Request
.Amount()
.setTotal(reqDTO
.getAmount()
.intValue())); // 单位分
request.setTimeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式
request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
request.setNotifyUrl(reqDTO.getNotifyUrl());
// 执行请求
return client.createOrderV3(TradeTypeEnum.JSAPI, request);
}
private static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {
String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid");
if (StrUtil.isEmpty(openid)) {
throw new IllegalArgumentException("支付请求的 openid 不能为空!");
}
return openid;
}
/**
*
* 微信支付回调 v2 和v3 的处理方式
*
* @param data 通知结果
* @return 支付回调对象
* @throws WxPayException 微信异常类
*/
// @Override
public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException {
log.info("[parseOrderNotify][微信支付回调data数据:{}]", data.getBody());
// 微信支付 v2 回调结果处理
switch (config.getApiVersion()) {
case WXPayClientConfig.API_VERSION_V2:
return parseOrderNotifyV2(data);
case WXPayClientConfig.API_VERSION_V3:
return parseOrderNotifyV3(data);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException {
WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null);
WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult();
// 转换结果
Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"),
"支付结果非 SUCCESS");
return PayOrderNotifyRespDTO
.builder()
.orderExtensionNo(result.getOutTradeNo())
.channelOrderNo(result.getTransactionId())
.channelUserId(result.getPayer().getOpenid())
.successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
.build();
}
private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException {
WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody());
Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS");
// 转换结果
return PayOrderNotifyRespDTO
.builder()
.orderExtensionNo(notifyResult.getOutTradeNo())
.channelOrderNo(notifyResult.getTransactionId())
.channelUserId(notifyResult.getOpenid())
.successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss"))
.build();
}
@Override
protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
//TODO 需要实现
throw new UnsupportedOperationException();
}
}

View File

@ -1,181 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import java.time.ZoneId;
import java.util.Date;
import java.util.Objects;
/**
* 微信 App 支付
*
* @author zwy
*/
@Slf4j
public class WXNativePayClient extends AbstractPayClient<WXPayClientConfig> {
private WxPayService client;
public WXNativePayClient(Long channelId, WXPayClientConfig config) {
super(channelId, PayChannelEnum.WX_NATIVE.getCode(), config);
}
@Override
protected void doInit() {
WxPayConfig payConfig = new WxPayConfig();
BeanUtil.copyProperties(config, payConfig, "keyContent");
payConfig.setTradeType(WxPayConstants.TradeType.NATIVE); // 设置使用 native 支付方式
// if (StrUtil.isNotEmpty(config.getKeyContent())) {
// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8));
// }
if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateCertContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath());
}
// 真实客户端
this.client = new WxPayServiceImpl();
client.setConfig(payConfig);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
throw new UnsupportedOperationException();
// // 这里原生的返回的是支付的 url 所以直接使用string接收
// // "invokeResponse": "weixin://wxpay/bizpayurl?pr=EGYAem7zz"
// String responseV3;
// try {
// switch (config.getApiVersion()) {
// case WXPayClientConfig.API_VERSION_V2:
// responseV3 = unifiedOrderV2(reqDTO).getCodeUrl();
// break;
// case WXPayClientConfig.API_VERSION_V3:
// responseV3 = this.unifiedOrderV3(reqDTO);
// break;
// default:
// throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
// }
// } catch (WxPayException e) {
// log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e);
// return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"),
// ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()), null, codeMapping);
// }
// return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, responseV3, codeMapping);
}
private WxPayNativeOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
//前端
String tradeType = reqDTO.getChannelExtras().get("trade_type");
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest
.newBuilder()
.outTradeNo(reqDTO.getMerchantOrderId())
.body(reqDTO.getBody())
.totalFee(reqDTO.getAmount().intValue()) // 单位分
.timeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX"))
.spbillCreateIp(reqDTO.getUserIp())
.notifyUrl(reqDTO.getNotifyUrl())
.productId(tradeType)
.build();
// 执行请求
return client.createOrder(request);
}
private String unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
request.setOutTradeNo(reqDTO.getMerchantOrderId());
request.setDescription(reqDTO.getBody());
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
request.setNotifyUrl(reqDTO.getNotifyUrl());
// 执行请求
return client.createOrderV3(TradeTypeEnum.NATIVE, request);
}
/**
*
* 微信支付回调 分v2 和v3 的处理方式
*
* @param data 通知结果
* @return 支付回调对象
* @throws WxPayException 微信异常类
*/
// @Override
public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException {
log.info("微信支付回调data数据:{}", data.getBody());
// 微信支付 v2 回调结果处理
switch (config.getApiVersion()) {
case WXPayClientConfig.API_VERSION_V2:
return parseOrderNotifyV2(data);
case WXPayClientConfig.API_VERSION_V3:
return parseOrderNotifyV3(data);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException {
WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null);
WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult();
// 转换结果
Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"),
"支付结果非 SUCCESS");
return PayOrderNotifyRespDTO
.builder()
.orderExtensionNo(result.getOutTradeNo())
.channelOrderNo(result.getTradeState())
.successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
.build();
}
private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException {
WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody());
Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS");
// 转换结果
return PayOrderNotifyRespDTO
.builder()
.orderExtensionNo(notifyResult.getOutTradeNo())
.channelOrderNo(notifyResult.getTransactionId())
.channelUserId(notifyResult.getOpenid())
.successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss"))
.build();
}
@Override
protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
// TODO 需要实现
throw new UnsupportedOperationException();
}
}

View File

@ -1,196 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Objects;
/**
* 微信支付公众号 PayClient 实现类
*
* @author 芋道源码
*/
@Slf4j
public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
private WxPayService client;
public WXPubPayClient(Long channelId, WXPayClientConfig config) {
super(channelId, PayChannelEnum.WX_PUB.getCode(), config);
}
@Override
protected void doInit() {
WxPayConfig payConfig = new WxPayConfig();
BeanUtil.copyProperties(config, payConfig, "keyContent");
payConfig.setTradeType(WxPayConstants.TradeType.JSAPI); // 设置使用 JS API 支付方式
// if (StrUtil.isNotEmpty(config.getKeyContent())) {
// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8));
// }
if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateCertContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath());
}
// 真实客户端
this.client = new WxPayServiceImpl();
client.setConfig(payConfig);
}
@Override
public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
throw new UnsupportedOperationException();
//
// WxPayMpOrderResult response;
// try {
// switch (config.getApiVersion()) {
// case WXPayClientConfig.API_VERSION_V2:
// response = this.unifiedOrderV2(reqDTO);
// break;
// case WXPayClientConfig.API_VERSION_V3:
// WxPayUnifiedOrderV3Result.JsapiResult responseV3 = this.unifiedOrderV3(reqDTO);
// // V3 的结果统一转换成 V2返回的字段是一致的
// response = new WxPayMpOrderResult();
// BeanUtil.copyProperties(responseV3, response, true);
// break;
// default:
// throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
// }
// } catch (WxPayException e) {
// log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e);
// return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"),
// ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()),null, codeMapping);
// }
// return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping);
}
private WxPayMpOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
.outTradeNo(reqDTO.getMerchantOrderId())
.body(reqDTO.getBody())
.totalFee(reqDTO.getAmount()) // 单位分
.timeExpire(formatDate(reqDTO.getExpireTime()))
.spbillCreateIp(reqDTO.getUserIp())
.openid(getOpenid(reqDTO))
.notifyUrl(reqDTO.getNotifyUrl())
.build();
// 执行请求
return client.createOrder(request);
}
private WxPayUnifiedOrderV3Result.JsapiResult unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
request.setOutTradeNo(reqDTO.getMerchantOrderId());
request.setDescription(reqDTO.getBody());
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount())); // 单位分
request.setTimeExpire(formatDate(reqDTO.getExpireTime()));
request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
request.setNotifyUrl(reqDTO.getNotifyUrl());
// 执行请求
return client.createOrderV3(TradeTypeEnum.JSAPI, request);
}
private static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {
String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid");
if (StrUtil.isEmpty(openid)) {
throw new IllegalArgumentException("支付请求的 openid 不能为空!");
}
return openid;
}
/**
*
* 微信支付回调 分v2 和v3 的处理方式
*
* @param data 通知结果
* @return 支付回调对象
* @throws WxPayException 微信异常类
*/
// @Override
public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException {
log.info("[parseOrderNotify][微信支付回调data数据: {}]", data.getBody());
// 微信支付 v2 回调结果处理
switch (config.getApiVersion()) {
case WXPayClientConfig.API_VERSION_V2:
return parseOrderNotifyV2(data);
case WXPayClientConfig.API_VERSION_V3:
return parseOrderNotifyV3(data);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException {
WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null);
WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult();
// 转换结果
Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"),
"支付结果非 SUCCESS");
return PayOrderNotifyRespDTO
.builder()
.orderExtensionNo(result.getOutTradeNo())
.channelOrderNo(result.getTradeState())
.successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
.build();
}
private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException {
WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody());
Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS");
// 转换结果
return PayOrderNotifyRespDTO
.builder()
.orderExtensionNo(notifyResult.getOutTradeNo())
.channelOrderNo(notifyResult.getTransactionId())
.channelUserId(notifyResult.getOpenid())
.successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss"))
.build();
}
@Override
protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
// TODO 需要实现
throw new UnsupportedOperationException();
}
private static String formatDate(LocalDateTime time) {
return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), "yyyy-MM-dd'T'HH:mm:ssXXX");
}
}

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 渠道统一的退款返回结果
*
* @author jason
*/
@Getter
@AllArgsConstructor
public enum PayChannelRefundRespEnum {
SUCCESS(1, "退款成功"),
FAILURE(2, "退款失败"),
PROCESSING(3,"退款处理中"),
CLOSED(4, "退款关闭");
private final Integer status;
private final String name;
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* 支付框架的错误码枚举
*
* 支付框架使用 2-002-000-000
*
* @author 芋道源码
*/
public interface PayFrameworkErrorCodeConstants {
ErrorCode PAY_UNKNOWN = new ErrorCode(2002000000, "未知错误,需要解析");
// ========== 配置相关相关 2002000100 ==========
// todo 芋艿如下的错误码怎么处理掉
ErrorCode PAY_CONFIG_APP_ID_ERROR = new ErrorCode(2002000100, "支付渠道 AppId 不正确");
ErrorCode PAY_CONFIG_SIGN_ERROR = new ErrorCode(2002000100, "签名错误"); // 例如说微信支付配置错了 mchId 或者 mchKey
// ========== 其它相关 2002000900 开头 ==========
// todo 芋艿如下的错误码怎么处理掉
ErrorCode PAY_OPENID_ERROR = new ErrorCode(2002000900, "无效的 openid"); // 例如说微信 openid 未授权过
ErrorCode PAY_PARAM_MISSING = new ErrorCode(2002000901, "请求参数缺失"); // 例如说支付少传了金额
ErrorCode PAY_EXCEPTION = new ErrorCode(2002000999, "调用异常");
}

View File

@ -1,22 +0,0 @@
package cn.iocoder.yudao.framework.pay.core.enums;
/**
* 退款通知, 统一的渠道退款状态
*
* @author jason
*/
public enum PayNotifyRefundStatusEnum {
/**
* 支付宝 全额退款 trade_status=TRADE_CLOSED 部分退款 trade_status=TRADE_SUCCESS
* 退款成功
*/
SUCCESS,
/**
* 支付宝退款通知没有这个状态
* 退款异常
*/
ABNORMAL;
}

View File

@ -1,15 +1,14 @@
package cn.iocoder.yudao.framework.pay.core.enums;
package cn.iocoder.yudao.framework.pay.core.enums.channel;
import cn.hutool.core.util.ArrayUtil;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 支付渠道的编码的枚举
* 枚举值
*
* @author 芋道源码
*/
@ -17,10 +16,11 @@ import lombok.Getter;
@AllArgsConstructor
public enum PayChannelEnum {
WX_PUB("wx_pub", "微信 JSAPI 支付", WXPayClientConfig.class), // 公众号网页
WX_LITE("wx_lite", "微信小程序支付", WXPayClientConfig.class),
WX_APP("wx_app", "微信 App 支付", WXPayClientConfig.class),
WX_NATIVE("wx_native", "微信 native 支付", WXPayClientConfig.class),
WX_PUB("wx_pub", "微信 JSAPI 支付", WxPayClientConfig.class), // 公众号网页
WX_LITE("wx_lite", "微信小程序支付", WxPayClientConfig.class),
WX_APP("wx_app", "微信 App 支付", WxPayClientConfig.class),
WX_NATIVE("wx_native", "微信 Native 支付", WxPayClientConfig.class),
WX_BAR("wx_bar", "微信付款码支付", WxPayClientConfig.class),
ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付", AlipayPayClientConfig.class),
ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付", AlipayPayClientConfig.class),
@ -30,8 +30,8 @@ public enum PayChannelEnum {
/**
* 编码
* <p>
* 参考 https://www.pingxx.com/api/支付渠道属性值.html
*
* 参考 <a href="https://www.pingxx.com/api/支付渠道属性值.html">支付渠道属性值</a>
*/
private final String code;
/**

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.framework.pay.core.enums;
package cn.iocoder.yudao.framework.pay.core.enums.order;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -10,15 +10,15 @@ import lombok.Getter;
*/
@Getter
@AllArgsConstructor
public enum PayDisplayModeEnum {
public enum PayOrderDisplayModeEnum {
URL("url"), // Redirect 跳转链接的方式
IFRAME("iframe"), // IFrame 内嵌链接的方式
IFRAME("iframe"), // IFrame 内嵌链接的方式目前暂时用不到
FORM("form"), // HTML 表单提交
QR_CODE("qr_code"), // 二维码的文字内容
QR_CODE_URL("qr_code_url"), // 二维码的图片链接
BAR_CODE("bar_code"), // 条形码
APP("app"), // 应用
APP("app"), // 应用AndroidiOS微信小程序微信公众号等需要做自定义处理的
;
/**

View File

@ -0,0 +1,56 @@
package cn.iocoder.yudao.framework.pay.core.enums.order;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
/**
* 渠道的支付状态枚举
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum PayOrderStatusRespEnum {
WAITING(0, "未支付"),
SUCCESS(10, "支付成功"),
REFUND(20, "已退款"),
CLOSED(30, "支付关闭"),
;
private final Integer status;
private final String name;
/**
* 判断是否支付成功
*
* @param status 状态
* @return 是否支付成功
*/
public static boolean isSuccess(Integer status) {
return Objects.equals(status, SUCCESS.getStatus());
}
/**
* 判断是否已退款
*
* @param status 状态
* @return 是否支付成功
*/
public static boolean isRefund(Integer status) {
return Objects.equals(status, REFUND.getStatus());
}
/**
* 判断是否支付关闭
*
* @param status 状态
* @return 是否支付关闭
*/
public static boolean isClosed(Integer status) {
return Objects.equals(status, CLOSED.getStatus());
}
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.framework.pay.core.enums.refund;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
/**
* 渠道的退款状态枚举
*
* @author jason
*/
@Getter
@AllArgsConstructor
public enum PayRefundStatusRespEnum {
WAITING(0, "等待退款"),
SUCCESS(10, "退款成功"),
FAILURE(20, "退款失败");
private final Integer status;
private final String name;
public static boolean isSuccess(Integer status) {
return Objects.equals(status, SUCCESS.getStatus());
}
public static boolean isFailure(Integer status) {
return Objects.equals(status, FAILURE.getStatus());
}
}

View File

@ -2,17 +2,14 @@ package cn.iocoder.yudao.framework.pay.core.client.impl;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPubPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -27,18 +24,20 @@ import java.io.FileNotFoundException;
@Disabled
public class PayClientFactoryImplIntegrationTest {
private static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do";
private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl();
/**
* {@link WXPubPayClient} V2 版本
* {@link WxPubPayClient} V2 版本
*/
@Test
public void testCreatePayClient_WX_PUB_V2() {
// 创建配置
WXPayClientConfig config = new WXPayClientConfig();
WxPayClientConfig config = new WxPayClientConfig();
config.setAppId("wx041349c6f39b268b");
config.setMchId("1545083881");
config.setApiVersion(WXPayClientConfig.API_VERSION_V2);
config.setApiVersion(WxPayClientConfig.API_VERSION_V2);
config.setMchKey("0alL64UDQdlCwiKZ73ib7ypaIjMns06p");
// 创建客户端
Long channelId = RandomUtil.randomLong();
@ -51,15 +50,15 @@ public class PayClientFactoryImplIntegrationTest {
}
/**
* {@link WXPubPayClient} V3 版本
* {@link WxPubPayClient} V3 版本
*/
@Test
public void testCreatePayClient_WX_PUB_V3() throws FileNotFoundException {
// 创建配置
WXPayClientConfig config = new WXPayClientConfig();
WxPayClientConfig config = new WxPayClientConfig();
config.setAppId("wx041349c6f39b268b");
config.setMchId("1545083881");
config.setApiVersion(WXPayClientConfig.API_VERSION_V3);
config.setApiVersion(WxPayClientConfig.API_VERSION_V3);
config.setPrivateKeyContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_key.pem")));
config.setPrivateCertContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_cert.pem")));
config.setApiV3Key("joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase");
@ -82,7 +81,7 @@ public class PayClientFactoryImplIntegrationTest {
// 创建配置
AlipayPayClientConfig config = new AlipayPayClientConfig();
config.setAppId("2021000118634035");
config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX);
config.setServerUrl(SERVER_URL_SANDBOX);
config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=");
config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB");
@ -106,7 +105,7 @@ public class PayClientFactoryImplIntegrationTest {
// 创建配置
AlipayPayClientConfig config = new AlipayPayClientConfig();
config.setAppId("2021000118634035");
config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX);
config.setServerUrl(SERVER_URL_SANDBOX);
config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=");
config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB");
@ -122,10 +121,10 @@ public class PayClientFactoryImplIntegrationTest {
private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() {
PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO();
reqDTO.setAmount(123);
reqDTO.setPrice(123);
reqDTO.setSubject("IPhone 13");
reqDTO.setBody("biubiubiu");
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
reqDTO.setOutTradeNo(String.valueOf(System.currentTimeMillis()));
reqDTO.setUserIp("127.0.0.1");
reqDTO.setNotifyUrl("http://127.0.0.1:8080");
return reqDTO;

View File

@ -1,8 +1,6 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient;
@ -22,9 +20,11 @@ import static org.mockito.Mockito.when;
public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
private static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do";
private final AlipayPayClientConfig config = new AlipayPayClientConfig()
.setAppId("2021000118634035")
.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX)
.setServerUrl(SERVER_URL_SANDBOX)
.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)
// TODO @tinakey 可以随机就好简洁一点哈
.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJ" +
@ -72,8 +72,8 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
// 这里设置可以直接随机整个对象
Long shopOrderId = System.currentTimeMillis();
PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO();
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
reqDTO.setAmount(1);
reqDTO.setOutTradeNo(String.valueOf(System.currentTimeMillis()));
reqDTO.setPrice(1);
reqDTO.setBody("内容:" + shopOrderId);
reqDTO.setSubject("标题:"+shopOrderId);
String notify="http://niubi.natapp1.cc/api/pay/order/notify";

View File

@ -0,0 +1,123 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.AbstractWxPayClient.formatDateV2;
/**
* {@link WxBarPayClient} 的集成测试用于快速调试微信条码支付
*
* @author 芋道源码
*/
@Disabled
public class WxBarPayClientIntegrationTest {
@Test
public void testPayV2() throws WxPayException {
// 创建 config 配置
WxPayConfig config = buildWxPayConfigV2();
// 创建 WxPayService 客户端
WxPayService client = new WxPayServiceImpl();
client.setConfig(config);
// 执行发起支付
WxPayMicropayRequest request = WxPayMicropayRequest.newBuilder()
.outTradeNo(String.valueOf(System.currentTimeMillis()))
.body("测试支付-body")
.detail("测试支付-detail")
.totalFee(1) // 单位分
.timeExpire(formatDateV2(LocalDateTimeUtils.addTime(Duration.ofMinutes(2))))
.spbillCreateIp("127.0.0.1")
.authCode("134298744426278497")
.build();
System.out.println("========= request ==========");
System.out.println(JsonUtils.toJsonPrettyString(request));
WxPayMicropayResult response = client.micropay(request);
System.out.println("========= response ==========");
System.out.println(JsonUtils.toJsonPrettyString(response));
}
@Test
public void testParseRefundNotifyV2() throws WxPayException {
// 创建 config 配置
WxPayConfig config = buildWxPayConfigV2();
// 创建 WxPayService 客户端
WxPayService client = new WxPayServiceImpl();
client.setConfig(config);
// 执行解析
String xml = "<xml><return_code>SUCCESS</return_code><appid><![CDATA[wx62056c0d5e8db250]]></appid><mch_id><![CDATA[1545083881]]></mch_id><nonce_str><![CDATA[ed8f02c21d15635cede114a42d0525a0]]></nonce_str><req_info><![CDATA[bGp+wB9DAHjoOO9Nw1iSmmIFdN2zZDhsoRWZBYdf/8bcpjowr4T8i2qjLsbMtvKQeVC5kBZOL/Agal3be6UPwnoantil+L+ojZgvLch7dXFKs/AcoxIYcVYyGka+wmnRJfUmuFRBgzt++8HOFsmJz6e2brYv1EAz+93fP2AsJtRuw1FEzodcg8eXm52hbE0KhLNqC2OyNVkn8AbOOrwIxSYobg2jVbuJ4JllYbEGIQ/6kWzNbVmMKhGJGYBy/NbUGKoQsoe4QeTQqcqQqVp08muxaOfJGThaN3B9EEMFSrog/3yT7ykVV6WQ5+Ygt89LplOf5ucWa4Ird7VJhHWtzI92ZePj4Omy1XkT1TRlwtDegA0S5MeQpM4WZ1taMrhxgmNkTUJ0JXFncx5e2KLQvbvD/HOcccx48Xv1c16JBz6G3501k8E++LWXgZ2TeNXwGsk6FyRZb0ApLyQHIx5ZtPo/UET9z3AmJCPXkrUsZ4WK46fDtbzxVPU2r8nTOcGCPbO0LUsGT6wpsuQVC4CisXDJwoZmL6kKwHfKs6mmUL2YZYzNfgoB/KgpJYSpC96kcpQyFvw+xuwqK2SXGZbAl9lADT+a83z04feQHSSIG3PCrX4QEWzpCZZ4+ySEz1Y34aoU20X9GtX+1LSwUjmQgwHrMBSvFm3/B7+IFM8OUqDB+Uvkr9Uvy7P2/KDvfy3Ih7GFcGd0C5NXpSvVTTfu1IlK/T3/t6MR/8iq78pp/2ZTYvO6eNDRJWaXYU+x6sl2dTs9n+2Z4W4AfYTvEyuxlx+aI19SqCJh7WmaFcAxidFl/9iqDjWiplb9+C6ijZv2hJtVjSCuoptIWpGDYItH7RAqlKHrx6flJD+M/5BceMHBv2w4OWCD9vPRLo8gl9o06ip0iflzO1dixhOAgLFjsQmQHNGFtR3EvCID+iS4FUlilwK+hcKNxrr0wp9Btkl9W1R9aTo289CUiIxx45skfCYzHwb+7Hqj3uTiXnep6zhCKZBAnPsDOvISXfBgXKufcFsTNtts09jX8H5/uMc9wyJ179H1cp+At1mIK2duwfo4Q9asfEoffl6Zn1olGdtEruxHGeVU0NwJ8V7RflC/Cx5RXtJ3sPJ/sHmVnBlVyR0=]]></req_info></xml>";
WxPayRefundNotifyResult response = client.parseRefundNotifyResult(xml);
System.out.println(response.getReqInfo());
}
@Test
public void testRefundV2() throws WxPayException {
// 创建 config 配置
WxPayConfig config = buildWxPayConfigV2();
// 创建 WxPayService 客户端
WxPayService client = new WxPayServiceImpl();
client.setConfig(config);
// 执行发起退款
WxPayRefundRequest request = new WxPayRefundRequest()
.setOutTradeNo("1689545667276")
.setOutRefundNo(String.valueOf(System.currentTimeMillis()))
.setRefundFee(1)
.setRefundDesc("就是想退了")
.setTotalFee(1);
System.out.println("========= request ==========");
System.out.println(JsonUtils.toJsonPrettyString(request));
WxPayRefundResult response = client.refund(request);
System.out.println("========= response ==========");
System.out.println(JsonUtils.toJsonPrettyString(response));
}
@Test
public void testRefundV3() throws WxPayException {
// 创建 config 配置
WxPayConfig config = buildWxPayConfigV2();
// 创建 WxPayService 客户端
WxPayService client = new WxPayServiceImpl();
client.setConfig(config);
// 执行发起退款
WxPayRefundV3Request request = new WxPayRefundV3Request()
.setOutTradeNo("1689506325635")
.setOutRefundNo(String.valueOf(System.currentTimeMillis()))
.setAmount(new WxPayRefundV3Request.Amount().setTotal(1).setRefund(1).setCurrency("CNY"))
.setReason("就是想退了");
System.out.println("========= request ==========");
System.out.println(JsonUtils.toJsonPrettyString(request));
WxPayRefundV3Result response = client.refundV3(request);
System.out.println("========= response ==========");
System.out.println(JsonUtils.toJsonPrettyString(response));
}
private WxPayConfig buildWxPayConfigV2() {
WxPayConfig config = new WxPayConfig();
config.setAppId("wx62056c0d5e8db250");
config.setMchId("1545083881");
config.setMchKey("dS1ngeN63JLr3NRbvPH9AJy3MyUxZdim");
// config.setSignType(WxPayConstants.SignType.MD5);
config.setKeyPath("/Users/yunai/Downloads/wx_pay/apiclient_cert.p12");
return config;
}
}

View File

@ -0,0 +1,83 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.AbstractWxPayClient.formatDateV3;
/**
* {@link WxNativePayClient} 的集成测试用于快速调试微信扫码支付
*
* @author 芋道源码
*/
@Disabled
public class WxNativePayClientIntegrationTest {
@Test
public void testPayV3() throws WxPayException {
// 创建 config 配置
WxPayConfig config = buildWxPayConfigV3();
// 创建 WxPayService 客户端
WxPayService client = new WxPayServiceImpl();
client.setConfig(config);
// 执行发起支付
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request()
.setOutTradeNo(String.valueOf(System.currentTimeMillis()))
.setDescription("测试支付-body")
.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(1)) // 单位分
.setTimeExpire(formatDateV3(LocalDateTimeUtils.addTime(Duration.ofMinutes(2))))
.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp("127.0.0.1"))
.setNotifyUrl("http://127.0.0.1:48080");
System.out.println("========= request ==========");
System.out.println(JsonUtils.toJsonPrettyString(request));
String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
System.out.println("========= response ==========");
System.out.println(JsonUtils.toJsonPrettyString(response));
}
@Test
public void testRefundV3() throws WxPayException {
// 创建 config 配置
WxPayConfig config = buildWxPayConfigV3();
// 创建 WxPayService 客户端
WxPayService client = new WxPayServiceImpl();
client.setConfig(config);
// 执行发起退款
WxPayRefundV3Request request = new WxPayRefundV3Request()
.setOutTradeNo("1689545729695")
.setOutRefundNo(String.valueOf(System.currentTimeMillis()))
.setAmount(new WxPayRefundV3Request.Amount().setTotal(1).setRefund(1).setCurrency("CNY"))
.setReason("就是想退了");
System.out.println("========= request ==========");
System.out.println(JsonUtils.toJsonPrettyString(request));
WxPayRefundV3Result response = client.refundV3(request);
System.out.println("========= response ==========");
System.out.println(JsonUtils.toJsonPrettyString(response));
}
private WxPayConfig buildWxPayConfigV3() {
WxPayConfig config = new WxPayConfig();
config.setAppId("wx62056c0d5e8db250");
config.setMchId("1545083881");
config.setApiV3Key("459arNsYHl1mgkiO6H9ZH5KkhFXSxaA4");
// config.setCertSerialNo(serialNo);
config.setPrivateCertPath("/Users/yunai/Downloads/wx_pay/apiclient_cert.pem");
config.setPrivateKeyPath("/Users/yunai/Downloads/wx_pay/apiclient_key.pem");
return config;
}
}

View File

@ -82,9 +82,9 @@ public class TenantUtils {
* 将多租户编号添加到 header
*
* @param headers HTTP 请求 headers
* @param tenantId 租户编号
*/
public static void addTenantHeader(Map<String, String> headers) {
Long tenantId = TenantContextHolder.getTenantId();
public static void addTenantHeader(Map<String, String> headers, Long tenantId) {
if (tenantId != null) {
headers.put(HEADER_TENANT_ID, tenantId.toString());
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.framework.excel.core.convert;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 金额转换器
*
* 金额单位
*
* @author 芋道源码
*/
public class MoneyConvert implements Converter<Integer> {
@Override
public Class<?> supportJavaTypeKey() {
throw new UnsupportedOperationException("暂不支持,也不需要");
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
throw new UnsupportedOperationException("暂不支持,也不需要");
}
@Override
public WriteCellData<String> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
BigDecimal result = BigDecimal.valueOf(value)
.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
return new WriteCellData<>(result.toString());
}
}

View File

@ -46,6 +46,18 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
}
default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
SFunction<T, ?> field3, Object value3) {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
.eq(field3, value3));
}
default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
SFunction<T, ?> field3, Object value3, SFunction<T, ?> field4, Object value4) {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
.eq(field3, value3).eq(field4, value4));
}
default Long selectCount() {
return selectCount(new QueryWrapper<T>());
}
@ -105,8 +117,26 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
update(update, new QueryWrapper<>());
}
/**
* 根据ID 批量更新适合大量数据更新
*
* @param entities 实体们
*/
default void updateBatch(Collection<T> entities) {
Db.updateBatchById(entities);
}
default void updateBatch(Collection<T> entities, int size) {
Db.updateBatchById(entities, size);
}
/**
* 批量修改插入, 会根据实体的主键是否为空更新还是修改默认为 1000
*
* @param entities 实体们
*/
default void saveOrUpdateBatch(Collection<T> entities){
Db.saveOrUpdateBatch(entities);
}
}

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.mybatis.core.query;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

View File

@ -0,0 +1,56 @@
package cn.iocoder.yudao.framework.mybatis.core.type;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
* List<Integer> 的类型转换器实现类对应数据库的 varchar 类型
*
* @author jason
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class IntegerListTypeHandler implements TypeHandler<List<Integer>> {
private static final String COMMA = ",";
@Override
public void setParameter(PreparedStatement ps, int i, List<Integer> strings, JdbcType jdbcType) throws SQLException {
ps.setString(i, CollUtil.join(strings, COMMA));
}
@Override
public List<Integer> getResult(ResultSet rs, String columnName) throws SQLException {
String value = rs.getString(columnName);
return getResult(value);
}
@Override
public List<Integer> getResult(ResultSet rs, int columnIndex) throws SQLException {
String value = rs.getString(columnIndex);
return getResult(value);
}
@Override
public List<Integer> getResult(CallableStatement cs, int columnIndex) throws SQLException {
String value = cs.getString(columnIndex);
return getResult(value);
}
private List<Integer> getResult(String value) {
if (value == null) {
return null;
}
return StrUtils.splitToInteger(value, COMMA);
}
}

View File

@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
@ -41,7 +40,6 @@ public class BaseDbAndRedisUnitTest {
// Redis 配置类
RedisTestConfiguration.class, // Redis 测试配置类用于启动 RedisServer
RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})

View File

@ -55,6 +55,9 @@ public class RandomUtils {
}
return RandomUtil.randomInt();
});
// LocalDateTime
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class,
(dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime());
// Boolean
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> {
// 如果是 deleted 的字段返回非删除
@ -82,7 +85,8 @@ public class RandomUtils {
}
public static LocalDateTime randomLocalDateTime() {
return LocalDateTimeUtil.of(randomDate());
// 设置 Nano 为零的原因避免 MySQLH2 存储不到时间戳
return LocalDateTimeUtil.of(randomDate()).withNano(0);
}
public static Short randomShort() {
@ -102,6 +106,10 @@ public class RandomUtils {
return randomString() + "@qq.com";
}
public static String randomURL() {
return "https://www.iocoder.cn/" + randomString();
}
@SafeVarargs
public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) {
T pojo = PODAM_FACTORY.manufacturePojo(clazz);

View File

@ -10,11 +10,14 @@ import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@ -113,4 +116,13 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
return bean;
}
/**
* 创建 RestTemplate 实例
*
* @param restTemplateBuilder {@link RestTemplateAutoConfiguration#restTemplateBuilder}
*/
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder.build();
}
}

View File

@ -3,16 +3,16 @@ package cn.iocoder.yudao.module.bpm.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* 工作流 错误码枚举类
* Bpm 错误码枚举类
*
* 工作流系统使用 1-009-000-000
* bpm 系统使用 1-009-000-000
*/
public interface ErrorCodeConstants {
// ========== 通用流程处理 模块 1-009-000-000 ==========
// ========== 通用流程处理 模块 1009000000 ==========
ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1009000002, "获取高亮流程图异常");
// ========== OA 流程模块 1-009-001-000 ==========
// ========== OA 流程模块 1009001000 ==========
ErrorCode OA_LEAVE_NOT_EXISTS = new ErrorCode(1009001001, "请假申请不存在");
ErrorCode OA_PM_POST_NOT_EXISTS = new ErrorCode(1009001002, "项目经理岗位未设置");
ErrorCode OA_DEPART_PM_POST_NOT_EXISTS = new ErrorCode(1009001009, "部门的项目经理不存在");
@ -21,7 +21,7 @@ public interface ErrorCodeConstants {
ErrorCode OA_HR_POST_NOT_EXISTS = new ErrorCode(1009001006, "HR岗位未设置");
ErrorCode OA_DAY_LEAVE_ERROR = new ErrorCode(1009001007, "请假天数必须>=1");
// ========== 流程模型 1-009-002-000 ==========
// ========== 流程模型 1009002000 ==========
ErrorCode MODEL_KEY_EXISTS = new ErrorCode(1009002000, "已经存在流程标识为【{}】的流程");
ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1009002001, "流程模型不存在");
ErrorCode MODEL_KEY_VALID = new ErrorCode(1009002002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");
@ -30,34 +30,34 @@ public interface ErrorCodeConstants {
"原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置");
ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1009003005, "流程定义部署失败,原因:信息未发生变化");
// ========== 流程定义 1-009-003-000 ==========
// ========== 流程定义 1009003000 ==========
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在");
ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003003, "流程定义处于挂起状态");
ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1009003004, "流程定义的模型不存在");
// ========== 流程实例 1-009-004-000 ==========
// ========== 流程实例 1009004000 ==========
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009004000, "流程实例不存在");
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1009004001, "流程取消失败,流程不处于运行中");
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1009004002, "流程取消失败,该流程不是你发起的");
// ========== 流程任务 1-009-005-000 ==========
// ========== 流程任务 1009005000 ==========
ErrorCode TASK_COMPLETE_FAIL_NOT_EXISTS = new ErrorCode(1009005000, "审批任务失败,原因:该任务不处于未审批");
ErrorCode TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1009005001, "审批任务失败,原因:该任务的审批人不是你");
// ========== 流程任务分配规则 1-009-006-000 ==========
// ========== 流程任务分配规则 1009006000 ==========
ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1009006000, "流程({}) 的任务({}) 已经存在分配规则");
ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1009006001, "流程任务分配规则不存在");
ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1009006002, "只有流程模型的任务分配规则,才允许被修改");
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1009006003, "操作失败,原因:找不到任务的审批人!");
ErrorCode TASK_ASSIGN_SCRIPT_NOT_EXISTS = new ErrorCode(1009006004, "操作失败,原因:任务分配脚本({}) 不存在");
// ========== 动态表单模块 1-009-010-000 ==========
// ========== 动态表单模块 1009010000 ==========
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在");
ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1009010001, "表单项({}) 和 ({}) 使用了相同的字段名({})");
// ========== 用户组模块 1-009-011-000 ==========
// ========== 用户组模块 1009011000 ==========
ErrorCode USER_GROUP_NOT_EXISTS = new ErrorCode(1009011000, "用户组不存在");
ErrorCode USER_GROUP_IS_DISABLE = new ErrorCode(1009011001, "名字为【{}】的用户组已被禁用");

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.product.api.comment;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
/**
* 产品评论 API 接口
*
* @author HUIHUI
*/
public interface ProductCommentApi {
/**
* 创建评论
*
* @param createReqDTO 评论参数
* @return 返回评论创建后的 id
*/
Long createComment(ProductCommentCreateReqDTO createReqDTO);
}

View File

@ -0,0 +1,59 @@
package cn.iocoder.yudao.module.product.api.comment.dto;
import lombok.Data;
import java.util.List;
/**
* 评论创建请求 DTO
*
* @author HUIHUI
*/
@Data
public class ProductCommentCreateReqDTO {
/**
* 商品 SKU 编号
*/
private Long skuId;
/**
* 订单编号
*/
private Long orderId;
/**
* 交易订单项编号
*/
private Long orderItemId;
/**
* 评分星级 1-5
*/
private Integer scores;
/**
* 描述星级 1-5
*/
private Integer descriptionScores;
/**
* 服务星级 1-5
*/
private Integer benefitScores;
/**
* 评论内容
*/
private String content;
/**
* 评论图片地址数组以逗号分隔最多上传 9
*/
private List<String> picUrls;
/**
* 是否匿名
*/
private Boolean anonymous;
/**
* 评价人
*/
private Long userId;
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.product.api.sku;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import java.util.Collection;
import java.util.List;
@ -30,6 +30,15 @@ public interface ProductSkuApi {
*/
List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
// TODO puhui999入参用 Collection<Long> 更通用
/**
* 批量查询 SKU 数组
*
* @param spuIds SPU 编号列表
* @return SKU 数组
*/
List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds);
/**
* 更新 SKU 库存
*

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.product.api.sku.dto;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import lombok.Data;
import java.util.List;
@ -22,15 +22,11 @@ public class ProductSkuRespDTO {
* SPU 编号
*/
private Long spuId;
/**
* SPU 名字
*/
private String spuName;
/**
* 属性数组JSON 格式
* 属性数组
*/
private List<Property> properties;
private List<ProductPropertyValueDetailRespDTO> properties;
/**
* 销售价格单位
*/
@ -51,20 +47,10 @@ public class ProductSkuRespDTO {
* 图片地址
*/
private String picUrl;
/**
* SKU 状态
* <p>
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 库存
*/
private Integer stock;
/**
* 预警预存
*/
private Integer warnStock;
/**
* 商品重量单位kg 千克
*/
@ -74,22 +60,4 @@ public class ProductSkuRespDTO {
*/
private Double volume;
/**
* 商品属性
*/
@Data
public static class Property {
/**
* 属性编号
*/
private Long propertyId;
/**
* 属性值编号
*/
private Long valueId;
}
}

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.product.api.spu.dto;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import lombok.Data;
@ -29,17 +28,23 @@ public class ProductSpuRespDTO {
*/
private String name;
/**
* 商品编码
* 关键字
*/
private String code;
private String keyword;
/**
* 促销语
* 商品简介
*/
private String sellPoint;
private String introduction;
/**
* 商品详情
*/
private String description;
// TODO @芋艿是不是要删除
/**
* 商品条码一维码
*/
private String barCode;
/**
* 商品分类编号
*/
@ -49,13 +54,13 @@ public class ProductSpuRespDTO {
*/
private Long brandId;
/**
* 商品图片的数组
* <p>
* 1. 第一张图片将作为商品主图支持同时上传多张图
* 2. 建议使用尺寸 800x800 像素以上大小不超过 1M 的正方形图片
* 3. 至少 1 最多上传 10
* 商品封面图
*/
private List<String> picUrls;
private String picUrl;
/**
* 商品轮播图
*/
private List<String> sliderPicUrls;
/**
* 商品视频
*/
@ -76,38 +81,36 @@ public class ProductSpuRespDTO {
/**
* 规格类型
* <p>
* 枚举 {@link ProductSpuSpecTypeEnum}
*
* false - 单规格
* true - 多规格
*/
private Integer specType;
private Boolean specType;
/**
* 最小价格单位使用
* <p>
* 基于其对应的 {@link ProductSkuRespDTO#getPrice()} 最小值
* 商品价格单位使用
*/
private Integer minPrice;
/**
* 最大价格单位使用
* <p>
* 基于其对应的 {@link ProductSkuRespDTO#getPrice()} 最大值
*/
private Integer maxPrice;
private Integer price;
/**
* 市场价单位使用
* <p>
* 基于其对应的 {@link ProductSkuRespDTO#getMarketPrice()} 最大值
*/
private Integer marketPrice;
/**
* 总库存
* <p>
* 基于其对应的 {@link ProductSkuRespDTO#getStock()} 求和
* 成本价单位使用
*/
private Integer totalStock;
private Integer costPrice;
/**
* 是否展示库存
* 库存
*/
private Boolean showStock;
private Integer stock;
// ========== 物流相关字段 =========
/**
* 物流配置模板编号
*
* 对应 TradeDeliveryExpressTemplateDO id 编号
*/
private Long deliveryTemplateId;
// ========== 统计相关字段 =========

View File

@ -0,0 +1,13 @@
package cn.iocoder.yudao.module.product.enums;
/**
* product 字典类型的枚举类
*
* @author HUIHUI
*/
public interface DictTypeConstants {
String PRODUCT_UNIT = "product_unit"; // 商品单位
String PRODUCT_SPU_STATUS = "product_spu_status"; // 商品 SPU 状态
}

View File

@ -15,10 +15,11 @@ public interface ErrorCodeConstants {
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1008001005, "类别下存在商品,无法删除");
// ========== 商品品牌相关编号 1008002000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌已禁用");
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
// ========== 商品属性项 1008003000 ==========
@ -32,8 +33,9 @@ public interface ErrorCodeConstants {
// ========== 商品 SPU 1008005000 ==========
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类");
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第二级的商品分类及以");
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1008005003, "商品 SPU 不处于回收站状态");
// ========== 商品 SKU 1008006000 ==========
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
@ -42,4 +44,14 @@ public interface ErrorCodeConstants {
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU必须不重复");
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
// ========== 商品 评价 1008007000 ==========
ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品 评价 不存在");
ErrorCode ORDER_SPU_COMMENT_EXISTS = new ErrorCode(1008007001, "订单 商品评价 已存在");
ErrorCode COMMENT_ERROR_OPT = new ErrorCode(1008007002, "商品评价非法操作");
ErrorCode COMMENT_ADDITIONAL_EXISTS = new ErrorCode(1008007003, "商品追加评价已存在");
// ========== 商品 收藏 1008008000 ==========
ErrorCode FAVORITE_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏");
ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1008008001, "商品收藏不存在");
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.product.enums;
/**
* Product 常量
*
* @author HUIHUI
*/
public interface ProductConstants {
/**
* 警戒库存 TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换
*/
int ALERT_STOCK = 10;
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.product.enums.comment;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品评论的星级枚举
*
* @author wangzhs
*/
@Getter
@AllArgsConstructor
public enum ProductCommentScoresEnum implements IntArrayValuable {
ONE(1, "1星"),
TWO(2, "2星"),
THREE(3, "3星"),
FOUR(4, "4星"),
FIVE(5, "5星");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductCommentScoresEnum::getScores).toArray();
/**
* 星级
*/
private final Integer scores;
/**
* 星级名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -1,37 +0,0 @@
package cn.iocoder.yudao.module.product.enums.spu;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品 SPU 规格类型
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum ProductSpuSpecTypeEnum implements IntArrayValuable {
RECYCLE(1, "统一规格"),
DISABLE(2, "多规格");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();
/**
* 规格类型
*/
private final Integer type;
/**
* 规格名称
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -17,7 +17,7 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
RECYCLE(-1, "回收站"),
DISABLE(0, "下架"),
ENABLE(1, "上架"),;
ENABLE(1, "上架");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuStatusEnum::getStatus).toArray();

View File

@ -23,12 +23,27 @@
<artifactId>yudao-module-product-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- TODO 芋艿:看看~~~ -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-trade-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-member-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.product.api.comment;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
/**
* 商品评论 API 实现类
*
* @author HUIHUI
*/
@Service
@Validated
public class ProductCommentApiImpl implements ProductCommentApi {
@Resource
private ProductCommentService productCommentService;
@Override
public Long createComment(ProductCommentCreateReqDTO createReqDTO) {
return productCommentService.createComment(createReqDTO);
}
}

View File

@ -15,7 +15,8 @@ import java.util.Collections;
import java.util.List;
/**
* TODO LeeYan9: 类注释;
* 商品 SKU API 实现类
*
* @author LeeYan9
* @since 2022-09-06
*/
@ -28,8 +29,8 @@ public class ProductSkuApiImpl implements ProductSkuApi {
@Override
public ProductSkuRespDTO getSku(Long id) {
// TODO TODO LeeYan9: 需要实现
return null;
ProductSkuDO sku = productSkuService.getSku(id);
return ProductSkuConvert.INSTANCE.convert02(sku);
}
@Override
@ -41,6 +42,15 @@ public class ProductSkuApiImpl implements ProductSkuApi {
return ProductSkuConvert.INSTANCE.convertList04(skus);
}
@Override
public List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds) {
if (CollUtil.isEmpty(spuIds)) {
return Collections.emptyList();
}
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds);
return ProductSkuConvert.INSTANCE.convertList04(skus);
}
@Override
public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) {
productSkuService.updateSkuStock(updateStockReqDTO);

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.product.api.spu;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
@ -14,7 +14,7 @@ import java.util.Collections;
import java.util.List;
/**
* TODO LeeYan9: 类注释;
* 商品 SPU API 接口实现类
*
* @author LeeYan9
* @since 2022-09-06
@ -28,11 +28,11 @@ public class ProductSpuApiImpl implements ProductSpuApi {
@Override
public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) {
// TODO TODO LeeYan9: AllEmpty?
if (CollectionUtils.isAnyEmpty(spuIds)) {
if (CollectionUtil.isEmpty(spuIds)) {
return Collections.emptyList();
}
List<ProductSpuDO> productSpuDOList = productSpuMapper.selectBatchIds(spuIds);
return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList);
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.brand;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*;
@ -62,6 +63,15 @@ public class ProductBrandController {
return success(ProductBrandConvert.INSTANCE.convert(brand));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<ProductBrandSimpleRespVO>> getSimpleBrandList() {
// 获取品牌列表只要开启状态的
List<ProductBrandDO> list = brandService.getBrandListByStatus(CommonStatusEnum.ENABLE.getStatus());
// 排序后返回给前端
return success(ProductBrandConvert.INSTANCE.convertList1(list));
}
@GetMapping("/page")
@Operation(summary = "获得品牌分页")
@PreAuthorize("@ss.hasPermission('product:brand:query')")

View File

@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull;
@Data
public class ProductBrandBaseVO {
@Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果")
@NotNull(message = "品牌名称不能为空")
private String name;

View File

@ -7,7 +7,7 @@ import lombok.Data;
@Data
public class ProductBrandListReqVO {
@Schema(description = "品牌名称", example = "芋道")
@Schema(description = "品牌名称", example = "苹果")
private String name;
}

View File

@ -17,7 +17,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@ToString(callSuper = true)
public class ProductBrandPageReqVO extends PageParam {
@Schema(description = "品牌名称", example = "芋道")
@Schema(description = "品牌名称", example = "苹果")
private String name;
@Schema(description = "状态", example = "0")

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 品牌精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductBrandSimpleRespVO {
@Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果")
private String name;
}

View File

@ -21,16 +21,16 @@ public class ProductCategoryBaseVO {
@NotBlank(message = "分类名称不能为空")
private String name;
@Schema(description = "分类图", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "分类图不能为空")
@Schema(description = "移动端分类图", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "移动端分类图不能为空")
private String picUrl;
@Schema(description = "PC 端分类图")
private String bigPicUrl;
@Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sort;
@Schema(description = "分类描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "描述")
private String description;
@Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "开启状态不能为空")
private Integer status;

View File

@ -5,10 +5,15 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
@Schema(description = "管理后台 - 商品分类创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductCategoryCreateReqVO extends ProductCategoryBaseVO {
@Schema(description = "分类描述", example = "描述")
private String description;
}

View File

@ -10,4 +10,10 @@ public class ProductCategoryListReqVO {
@Schema(description = "分类名称", example = "办公文具")
private String name;
@Schema(description = "开启状态", example = "0")
private Integer status;
@Schema(description = "父分类编号", example = "1")
private Long parentId;
}

View File

@ -5,6 +5,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 商品分类更新 Request VO")
@ -17,4 +18,7 @@ public class ProductCategoryUpdateReqVO extends ProductCategoryBaseVO {
@NotNull(message = "分类编号不能为空")
private Long id;
@Schema(description = "分类描述", example = "描述")
private String description;
}

View File

@ -0,0 +1,62 @@
package cn.iocoder.yudao.module.product.controller.admin.comment;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.*;
import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 商品评价")
@RestController
@RequestMapping("/product/comment")
@Validated
public class ProductCommentController {
@Resource
private ProductCommentService productCommentService;
@GetMapping("/page")
@Operation(summary = "获得商品评价分页")
@PreAuthorize("@ss.hasPermission('product:comment:query')")
public CommonResult<PageResult<ProductCommentRespVO>> getCommentPage(@Valid ProductCommentPageReqVO pageVO) {
PageResult<ProductCommentDO> pageResult = productCommentService.getCommentPage(pageVO);
return success(ProductCommentConvert.INSTANCE.convertPage(pageResult));
}
@PutMapping("/update-visible")
@Operation(summary = "显示 / 隐藏评论")
@PreAuthorize("@ss.hasPermission('product:comment:update')")
public CommonResult<Boolean> updateCommentVisible(@Valid @RequestBody ProductCommentUpdateVisibleReqVO updateReqVO) {
productCommentService.updateCommentVisible(updateReqVO);
return success(true);
}
@PutMapping("/reply")
@Operation(summary = "商家回复")
@PreAuthorize("@ss.hasPermission('product:comment:update')")
public CommonResult<Boolean> commentReply(@Valid @RequestBody ProductCommentReplyReqVO replyVO) {
productCommentService.replyComment(replyVO, getLoginUserId());
return success(true);
}
@PutMapping("/create")
@Operation(summary = "添加自评")
@PreAuthorize("@ss.hasPermission('product:comment:update')")
public CommonResult<Boolean> createComment(@Valid @RequestBody ProductCommentCreateReqVO createReqVO) {
productCommentService.createComment(createReqVO);
return success(true);
}
}

View File

@ -0,0 +1,62 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
@Data
public class ProductCommentBaseVO {
@Schema(description = "评价人", requiredMode = Schema.RequiredMode.REQUIRED, example = "16868")
@NotNull(message = "评价人不能为空")
private Long userId;
@Schema(description = "评价订单项", requiredMode = Schema.RequiredMode.REQUIRED, example = "19292")
@NotNull(message = "评价订单项不能为空")
private Long orderItemId;
@Schema(description = "评价人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小姑凉")
@NotNull(message = "评价人名称不能为空")
private String userNickname;
@Schema(description = "评价人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
@NotNull(message = "评价人头像不能为空")
private String userAvatar;
// TODO @puhuispuIdspuName 是不是只有 ProductCommentRespVO 有呀
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")
@NotNull(message = "商品 SPU 编号不能为空")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotNull(message = "商品 SPU 名称不能为空")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "评分星级不能为空")
private Integer scores;
@Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "描述星级不能为空")
private Integer descriptionScores;
@Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "服务星级分不能为空")
private Integer benefitScores;
@Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "穿起来非常丝滑凉快")
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
private List<String> picUrls;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 商品评价创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductCommentCreateReqVO extends ProductCommentBaseVO {
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 商品评价分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductCommentPageReqVO extends PageParam {
@Schema(description = "评价人名称", example = "王二狗")
private String userNickname;
@Schema(description = "交易订单编号", example = "24428")
private Long orderId;
@Schema(description = "商品SPU编号", example = "29502")
private Long spuId;
@Schema(description = "商品SPU名称", example = "感冒药")
private String spuName;
@Schema(description = "评分星级 1-5 分", example = "5")
@InEnum(ProductCommentScoresEnum.class)
private Integer scores;
// TODO @puhui999replyStatus
@Schema(description = "商家是否回复", example = "true")
private Boolean replied;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

Some files were not shown because too many files have changed in this diff Show More