feat(channel): 通道连通性 demo 链路, 含声明式通道客户端与 traceparent 透传

This commit is contained in:
DaxPay Dev
2026-06-23 13:56:27 +08:00
parent ab70a099f6
commit 002688eeeb
20 changed files with 504 additions and 39 deletions

View File

@@ -12,7 +12,7 @@
Target Server Version : 160009 (160009)
File Encoding : 65001
Date: 17/06/2026 18:12:21
Date: 23/06/2026 09:16:48
*/
@@ -103,7 +103,6 @@ INSERT INTO "public"."iam_perm_menu" VALUES (302, 3, NULL, 'admin', 'SystemLog',
INSERT INTO "public"."iam_perm_menu" VALUES (30102, 301, 'iam:perm:menu', 'admin', 'SystemMenu', '菜单管理', 'Menu Management', 'menu.system.basic.menu', 'carbon:menu', 'f', 'f', '/iam/perm/menu/MenuList', '/system/basic/menu', NULL, 0, 'f', 't', 'f', 0, 1, 2, 'f', 'menu', NULL, NULL, NULL, NULL, '', '', '2026-03-20 03:11:13.134079+00', '2026-03-31 13:39:34.260955+00');
INSERT INTO "public"."iam_perm_menu" VALUES (30201, 302, 'starter:log:login', 'admin', 'SystemLoginLog', '登录日志', 'Login Log', 'menu.system.log.login', 'lucide:log-in', 'f', 'f', '/system/log/login/LoginLogList', '/system/log/login', NULL, 1, 'f', 't', 'f', 0, 1, 1, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-03-20 03:11:13.134079+00', '2026-03-30 15:25:09.855555+00');
INSERT INTO "public"."iam_perm_menu" VALUES (2, NULL, NULL, 'admin', 'Demos', '演示', 'Demos', 'menu.demos', 'ic:baseline-view-in-ar', 'f', 'f', NULL, '/demos', NULL, 1000, 'f', 't', 'f', 0, NULL, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-03-20 03:11:13.134079+00', '2026-03-20 03:11:13.134079+00');
INSERT INTO "public"."iam_perm_menu" VALUES (201, 2, NULL, 'admin', 'AntDesignDemos', 'Antd Next演示', 'Antd Next Demo', 'menu.demos.antd', 'lucide:box', 'f', 'f', '/demos/antd/AntdDemo', '/demos/ant-design-next', NULL, 1, 'f', 'f', 'f', 0, NULL, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-03-20 03:11:13.134079+00', '2026-03-20 03:11:13.134079+00');
INSERT INTO "public"."iam_perm_menu" VALUES (30202, 302, 'starter:log:operate', 'admin', 'SystemOperateLog', '操作日志', 'Operate Log', 'menu.system.log.operate', 'lucide:activity', 'f', 'f', '/system/log/operate/OperateLogList', '/system/log/operate', NULL, 2, 'f', 't', 'f', 0, 1, 1, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-03-20 03:11:13.134079+00', '2026-03-30 15:24:57.076166+00');
INSERT INTO "public"."iam_perm_menu" VALUES (1, NULL, NULL, 'admin', 'Dashboard', '仪表板', 'Dashboard', 'menu.dashboard', 'lucide:layout-dashboard', 'f', 'f', NULL, '/dashboard', '/analytics', -1, 'f', 'f', 'f', 0, NULL, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-03-20 03:11:13.134079+00', '2026-03-20 03:11:13.134079+00');
INSERT INTO "public"."iam_perm_menu" VALUES (30402, 304, 'system:platform:config', 'admin', 'PlatformConfig', '平台配置', 'Platform Config', 'menu.system.config.platform', 'lucide:settings', 'f', 'f', '/system/config/platform/PlatformConfig', '/system/config/platform', NULL, 2, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-07 16:00:00+00', '2026-04-07 16:00:00+00');
@@ -116,13 +115,10 @@ INSERT INTO "public"."iam_perm_menu" VALUES (40401, 404, 'payment:merchant:info'
INSERT INTO "public"."iam_perm_menu" VALUES (401, 4, 'payment:platform', 'admin', 'PaymentPlatform', '支付主数据', 'Payment Master Data', 'menu.payment.platform', 'lucide:building', 'f', 'f', NULL, '/payment/platform', NULL, 1, 'f', 't', 'f', 0, 1, 3, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-05 16:00:00+00', '2026-05-28 06:25:42.880461+00');
INSERT INTO "public"."iam_perm_menu" VALUES (203, 2, 'demos:region', 'admin', 'RegionCascaderDemo', '行政区划选择器', 'Region Cascader', 'menu.demos.region', 'lucide:map-pin', 'f', 'f', '/demos/region/RegionCascaderDemo', '/demos/region', NULL, 3, 'f', 't', 'f', 0, NULL, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-24 16:00:00+00', '2026-04-24 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040103, 40401, 'payment:merchant:manage:info', 'admin', 'MchInfoManage', '商户信息', 'Merchant Info', 'menu.payment.merchant.manage.info', NULL, 't', 'f', '/payment/merchant/manage/info/MchInfoManage', '/payment/merchant/manage/info', NULL, 3, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-01 16:00:00+00', '2026-05-01 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040104, 40401, 'payment:merchant:manage:entity', 'admin', 'MchEntityManage', '主体信息', 'Entity Info', 'menu.payment.merchant.manage.entity', NULL, 't', 'f', '/payment/merchant/manage/entity/MchEntityManage', '/payment/merchant/manage/entity', NULL, 4, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-01 16:00:00+00', '2026-05-01 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040105, 40401, 'payment:merchant:manage:settle', 'admin', 'MchSettleManage', '结算账户', 'Settle Account', 'menu.payment.merchant.manage.settle', NULL, 't', 'f', '/payment/merchant/manage/settle/MchSettleManage', '/payment/merchant/manage/settle', NULL, 5, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-01 16:00:00+00', '2026-05-01 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4, NULL, 'payment:system', 'admin', 'PaymentSystem', '平台管理', 'Platform Management', 'menu.platform', 'lucide:credit-card', 'f', 'f', NULL, '/payment', NULL, 3, 'f', 't', 'f', 0, 1, 1, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-05 16:00:00+00', '2026-06-13 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040102, 40401, 'payment:merchant:manage:credentialConfig', 'admin', 'MerchantCredentialConfig', '对接配置', 'Credential Config', 'menu.payment.merchant.manage.credentialConfig', NULL, 't', 'f', '/payment/merchant/manage/credential/MerchantCredentialConfig', '/payment/merchant/manage/credential', NULL, 3, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-01 16:00:00+00', '2026-05-01 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040101, 40401, 'payment:merchant:manage', 'admin', 'MerchantManage', '商户管理', 'Merchant Management', 'menu.payment.merchant.manage', '', 't', 'f', '/payment/merchant/manage/workbench/MerchantManage', '/payment/merchant/manage', NULL, 2, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-13 16:00:00+00', '2026-05-02 06:57:49.052168+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040106, 40401, 'payment:merchant:channelMerchant', 'admin', 'ChannelMerchant', '通道商户', 'Channel Merchant', 'menu.payment.merchant.channelMerchant', NULL, 't', 'f', '/payment/merchant/channel-merchant/ChannelMerchantList', '/payment/merchant/channel-merchant', NULL, 6, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-03 16:00:00+00', '2026-05-03 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040107, 40401, 'payment:merchant:product', 'admin', 'MchProductConfig', '支付产品', 'Payment Product', 'menu.payment.merchant.product', NULL, 't', 'f', '/payment/merchant/product/MchProductConfig', '/payment/merchant/product', NULL, 7, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-03 16:00:00+00', '2026-05-03 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040108, 40401, 'payment:merchant:user', 'admin', 'MerchantUser', '商户用户', 'Merchant User', 'menu.payment.merchant.user', '', 't', 'f', '/payment/merchant/user/MerchantUserList', '/payment/merchant/user', NULL, 8, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-04 16:00:00+00', '2026-05-04 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040109, 40401, 'payment:merchant:channelMerchant:create', 'admin', 'ChannelMerchantCreate', '创建通道商户', 'Create Channel Merchant', 'menu.payment.merchant.channelMerchant.create', NULL, 't', 'f', '/payment/merchant/channel-merchant/ChannelMerchantCreate', '/payment/merchant/channel-merchant/create', NULL, 9, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-05 16:00:00+00', '2026-05-05 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040111, 4040110, 'payment:merchant:app:payRoute', 'admin', 'PayRouteConfig', '通道路由', 'Channel Routing', 'menu.payment.merchant.app.payRoute', NULL, 't', 'f', '/payment/merchant/route/PayRouteConfig', '/payment/merchant/route', NULL, 2, 'f', 't', 'f', 1, 1, 1, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-24 22:23:46.483985+00', '2026-05-26 20:03:06.445803+00');
@@ -130,24 +126,24 @@ INSERT INTO "public"."iam_perm_menu" VALUES (4040110, 40401, 'payment:merchant:a
INSERT INTO "public"."iam_perm_menu" VALUES (601, 6, NULL, 'admin', 'TransactionIndex', '功能开发中', 'Coming Soon', 'menu.trade.index', 'lucide:construction', 'f', 'f', '/_core/fallback/coming-soon', '/trade/index', NULL, 1, 'f', 'f', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-24 16:00:00+00', '2026-05-24 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (7, NULL, 'terminal:system', 'admin', 'TerminalManagement', '终端管理', 'Terminal Management', 'menu.terminal', 'lucide:smartphone', 'f', 'f', NULL, '/terminal', '/terminal/index', 4.5, 'f', 't', 'f', 1, 1, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-24 16:00:00+00', '2026-05-24 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (701, 7, NULL, 'admin', 'TerminalIndex', '功能开发中', 'Coming Soon', 'menu.terminal.index', 'lucide:construction', 'f', 'f', '/_core/fallback/coming-soon', '/terminal/index', NULL, 1, 'f', 'f', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-24 16:00:00+00', '2026-05-24 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40103, 401, 'payment:platform:channel', 'admin', 'PayChannelList', '支付通道', 'Payment Channel', 'menu.payment.platform.channel', 'lucide:radio-tower', 'f', 'f', '/payment/masterdata/channel/PayChannelList', '/payment/platform/pay-channel', NULL, 0, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-28 16:00:00+00', '2026-05-28 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40104, 401, 'payment:platform:capability', 'admin', 'PayCapabilityList', '支付能力', 'Payment Capability', 'menu.payment.platform.capability', 'lucide:zap', 'f', 'f', '/payment/masterdata/capability/PayCapabilityList', '/payment/platform/pay-capability', NULL, 3, 'f', 't', 'f', 1, 1, 4, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-26 16:00:00+00', '2026-05-28 06:43:27.505831+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40101, 401, 'payment:platform:product', 'admin', 'ProductList', '支付产品', 'Payment Product', 'menu.payment.platform.product', 'lucide:package', 'f', 'f', '/payment/masterdata/product/PayProductList', '/payment/platform/product', NULL, 2, 'f', 't', 'f', 1, 1, 3, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-23 16:00:00+00', '2026-05-28 06:25:42.892396+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040112, 40401, 'payment:merchant:channelMerchant:detail', 'admin', 'ChannelMerchantDetailDispatch', '通道商户详情', 'Channel Merchant Detail', 'menu.payment.merchant.channelMerchant.detail', NULL, 't', 'f', '/payment/merchant/channel-merchant/detail/ChannelMerchantDetailDispatch', '/payment/merchant/channel-merchant/detail', NULL, 10, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-07 19:48:34.936565+00', '2026-06-07 19:48:34.936565+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040113, 40401, 'payment:merchant:channelMerchant:wechatApp', 'admin', 'WechatMchAppManage', '微信通道商户应用', 'WeChat Channel Merchant App', 'menu.payment.merchant.channelMerchant.wechatApp', NULL, 't', 'f', '/payment/channel/wechat/manage/mch/app/WechatMchAppManage', '/payment/merchant/channel-merchant/wechat-app-manage', NULL, 11, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-07 23:57:13.620205+00', '2026-06-07 23:57:13.620205+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040114, 40401, 'payment:merchant:channelMerchant:alipayApp', 'admin', 'AlipayMchAppManage', '支付宝通道商户应用', 'Alipay Channel Merchant App', 'menu.payment.merchant.channelMerchant.alipayApp', NULL, 't', 'f', '/payment/channel/alipay/manage/mch/app/AlipayMchAppManage', '/payment/merchant/channel-merchant/alipay-app-manage', NULL, 12, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-11 22:28:11.274785+00', '2026-06-11 22:28:11.274785+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40104, 401, 'payment:platform:capability', 'admin', 'PayCapabilityList', '支付能力', 'Payment Capability', 'menu.payment.platform.capability', 'lucide:zap', 'f', 'f', '/payment/masterdata/capability/PayCapabilityList', '/payment/platform/pay-capability', NULL, 3, 'f', 't', 'f', 1, 1, 4, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-26 16:00:00+00', '2026-05-28 06:43:27.505831+00');
INSERT INTO "public"."iam_perm_menu" VALUES (404, NULL, 'payment:merchant', 'admin', 'PaymentMerchant', '商户管理', 'Merchant Management', 'menu.payment.merchant', 'lucide:store', 'f', 'f', NULL, '/payment/merchant', NULL, 4, 't', 't', 'f', 0, NULL, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-05 16:00:00+00', '2026-06-13 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40102, 401, 'payment:platform:provider', 'admin', 'PayProviderList', '支付方式', 'Payment Method', 'menu.payment.platform.provider', 'lucide:list-tree', 'f', 'f', '/payment/masterdata/provider/PayProviderList', '/payment/platform/pay-method', NULL, 1, 'f', 't', 'f', 1, 1, 5, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-27 20:18:01.383008+00', '2026-05-30 08:21:19.464024+00');
INSERT INTO "public"."iam_perm_menu" VALUES (30403, 304, 'system:credential:config', 'admin', 'PlatformCredentialConfig', '对接配置', 'Credential Config', 'menu.system.config.credential', 'lucide:key-round', 'f', 'f', '/system/config/credential/PlatformCredentialConfig', '/system/config/credential', NULL, 3, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40102, 401, 'payment:platform:provider', 'admin', 'PayProviderList', '支付方式', 'Payment Method', 'menu.payment.platform.provider', 'lucide:list-tree', 'f', 'f', '/payment/masterdata/provider/PayMethodList', '/payment/platform/pay-method', NULL, 1, 'f', 't', 'f', 1, 1, 5, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-27 20:18:01.383008+00', '2026-05-30 08:21:19.464024+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40103, 401, 'payment:platform:channel', 'admin', 'PayChannelList', '支付通道', 'Payment Channel', 'menu.payment.platform.channel', 'lucide:radio-tower', 'f', 'f', '/payment/masterdata/channel/PayChannelList', '/payment/platform/pay-channel', NULL, 0, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-05-28 16:00:00+00', '2026-05-28 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40101, 401, 'payment:platform:product', 'admin', 'ProductList', '支付产品', 'Payment Product', 'menu.payment.platform.product', 'lucide:package', 'f', 'f', '/payment/masterdata/product/PayProductList', '/payment/platform/product', NULL, 2, 'f', 't', 'f', 1, 1, 3, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-23 16:00:00+00', '2026-05-28 06:25:42.892396+00');
INSERT INTO "public"."iam_perm_menu" VALUES (405, 4, 'payment:config', 'admin', 'PaymentConfig', '支付配置', 'Payment Config', 'menu.payment.config', 'lucide:settings-2', 'f', 'f', NULL, '/payment/config', NULL, 2, 'f', 't', 'f', 1, 1, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-14 00:00:00+00', '2026-06-14 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40105, 405, 'payment:config:productConfig', 'admin', 'ProductConfig', '支付产品管理', 'Payment Product Management', 'menu.payment.config.productConfig', 'lucide:layout-grid', 'f', 'f', '/payment/config/product/ProductConfig', '/payment/config/product', NULL, 1, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 09:14:10.179605+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40501, 405, 'payment:config:productDetail', 'admin', 'ProductDetailDispatch', '支付产品详情', 'Payment Product Detail', 'menu.payment.config.productDetail', NULL, 't', 'f', '/payment/config/product/detail/ProductDetailDispatch', '/payment/product-detail', NULL, 2, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-14 00:00:00+00', '2026-06-14 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40502, 405, 'payment:alipay:isvApp', 'admin', 'AlipayIsvAppManage', '支付宝服务商应用', 'Alipay ISV Application', 'menu.payment.alipay.isvApp', NULL, 't', 'f', '/payment/channel/alipay/manage/app/AlipayIsvAppManage', '/payment/config/product/app-manage', NULL, 3, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-14 00:00:00+00', '2026-06-14 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (40503, 405, 'payment:wechat:isvApp', 'admin', 'WechatIsvAppManage', '微信服务商应用', 'WeChat ISV Application', 'menu.payment.wechat.isvApp', NULL, 't', 'f', '/payment/channel/wechat/manage/app/WechatIsvAppManage', '/payment/config/product/wechat-app-manage', NULL, 4, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-14 00:00:00+00', '2026-06-14 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040115, 40401, 'payment:merchant:channelMerchant:douyinApp', 'admin', 'DouyinMchAppManage', '抖音通道商户应用', 'Douyin Channel Merchant App', 'menu.payment.merchant.channelMerchant.douyinApp', NULL, 't', 'f', '/payment/channel/douyin/manage/app/DouyinMchAppManage', '/payment/merchant/channel-merchant/douyin-app-manage', NULL, 13, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-15 16:00:00+00', '2026-06-15 16:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040116, 401, 'payment:platform:provider', 'admin', 'PayProviderManage', '支付渠道', 'Payment Provider', 'menu.payment.platform.provider.manage', 'lucide:wallet', 'f', 'f', '/payment/masterdata/provider/PayProviderManage', '/payment/platform/pay-provider/manage', NULL, 0.5, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-17 10:00:31.640482+00', '2026-06-17 10:00:31.640482+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040117, 401, 'payment:platform:provider', 'admin', 'PayProviderManage', '支付渠道', 'Payment Provider', 'menu.payment.platform.provider.manage', 'lucide:wallet', 'f', 'f', '/payment/masterdata/provider/PayProviderManage', '/payment/platform/pay-provider', NULL, 0.5, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-17 10:10:32.614861+00', '2026-06-17 10:10:32.614861+00');
INSERT INTO "public"."iam_perm_menu" VALUES (4040116, 401, 'payment:platform:provider', 'admin', 'PayProviderManage', '支付渠道', 'Payment Provider', 'menu.payment.platform.provider.manage', 'lucide:wallet', 'f', 'f', '/payment/masterdata/provider/PayProviderList', '/payment/platform/pay-provider', NULL, 0.5, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-17 10:00:31.640482+00', '2026-06-17 10:00:31.640482+00');
INSERT INTO "public"."iam_perm_menu" VALUES (204, 2, 'demos:artemis', 'admin', 'ArtemisDemo', '消息队列演示', 'Message Queue Demo', 'menu.demos.artemis', 'lucide:send', 'f', 'f', '/demos/artemis/ArtemisDemo', '/demos/artemis', NULL, 4, 'f', 't', 'f', 0, NULL, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-18 00:00:00+00', '2026-06-18 00:00:00+00');
INSERT INTO "public"."iam_perm_menu" VALUES (900001, 304, 'iam:social:config', 'admin', 'SocialConfig', '三方平台登录', 'Third-party Platform Login', 'menu.system.config.social', 'lucide:share-2', 'f', 'f', 'views/iam/social/social-config', '/system/config/social', NULL, 5, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO "public"."iam_perm_menu" VALUES (205, 2, 'demos:channel', 'admin', 'ChannelDemo', '通道连通性演示', 'Channel Connectivity Demo', 'menu.demos.channel', 'lucide:radio-tower', 'f', 'f', '/demos/channel/ChannelDemo', '/demos/channel', NULL, 5, 'f', 't', 'f', 0, NULL, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-23 00:00:00+00', '2026-06-23 00:00:00+00');
-- ----------------------------
-- Primary Key structure for table iam_perm_menu

View File

@@ -0,0 +1,20 @@
package cn.daxpay.open.channel.alipay.client;
import cn.daxpay.open.channel.alipay.dto.AlipayPayReq;
import cn.daxpay.open.channel.alipay.dto.AlipayPayResp;
import cn.daxpay.open.payment.common.result.DaxResult;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.service.annotation.HttpExchange;
import org.springframework.web.service.annotation.PostExchange;
/// # 支付宝通道客户端
///
/// 声明式 HTTP 接口, 调用子应用 dax-pay-channel-one 的支付宝通道接口。
@HttpExchange(accept = MediaType.APPLICATION_JSON_VALUE, contentType = MediaType.APPLICATION_JSON_VALUE)
public interface AlipayChannelClient {
/// 支付下单
@PostExchange("/channel/pay")
DaxResult<AlipayPayResp> pay(@RequestBody AlipayPayReq req);
}

View File

@@ -0,0 +1,34 @@
package cn.daxpay.open.channel.alipay.config;
import cn.daxpay.open.channel.alipay.client.AlipayChannelClient;
import cn.daxpay.open.platform.common.config.properties.DaxpayChannelProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.support.RestClientAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
///
/// 复用全局 [RestClient](由 common-spring 的 RestClientConfiguration 提供, 已预装:
/// OTel traceparent 透传 / BusinessContextInterceptor 业务上下文透传 / Apache HttpClient5 连接池),
/// 经 `mutate()` 派生出绑定 channel-one baseUrl 的实例。
///
/// baseUrl 从 [DaxpayChannelProperties] 统一读取。
@Configuration
public class AlipayClientConfig {
@Bean
public AlipayChannelClient alipayChannelClient(
RestClient restClient,
DaxpayChannelProperties channelProperties) {
// mutate 派生: 继承全局 RestClient 的拦截器 / observation / requestFactory, 仅覆盖 baseUrl
RestClient channelClient = restClient
.mutate()
.baseUrl(channelProperties.getOne().getBaseUrl())
.build();
return HttpServiceProxyFactory
.builderFor(RestClientAdapter.create(channelClient))
.build()
.createClient(AlipayChannelClient.class);
}
}

View File

@@ -0,0 +1,21 @@
package cn.daxpay.open.channel.alipay.dto;
import lombok.Data;
import java.util.Map;
/// # 支付宝通道支付请求
///
/// 与子应用 ChannelPayReq 字段一致, 通过 Jackson 序列化传输
@Data
public class AlipayPayReq {
private String channel;
private String bizOrderNo;
private Long amount;
private String subject;
private String description;
private String method;
private String expireTime;
private String otherMethod;
private Map<String, Object> config;
}

View File

@@ -0,0 +1,17 @@
package cn.daxpay.open.channel.alipay.dto;
import lombok.Data;
/// # 支付宝通道支付响应
///
/// 与子应用 ChannelPayResp 字段一致
@Data
public class AlipayPayResp {
private String bizOrderNo;
private String outOrderNo;
private String transOrderNo;
private String payBody;
private String payBodyType;
private Boolean complete;
private String finishTime;
}

View File

@@ -1,24 +1,35 @@
package cn.daxpay.open.channel.alipay.service.pay;
import cn.daxpay.open.channel.alipay.client.AlipayChannelClient;
import cn.daxpay.open.channel.alipay.dto.AlipayPayReq;
import cn.daxpay.open.channel.alipay.dto.AlipayPayResp;
import cn.daxpay.open.payment.common.result.DaxResult;
import cn.daxpay.open.payment.pay.bo.PayTradeResultBo;
import cn.daxpay.open.payment.pay.order.entity.PayTrade;
import cn.daxpay.open.payment.unipay.param.trade.pay.PayParam;
import cn.daxpay.open.platform.core.enums.unipay.PayBodyTypeEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
/// # 支付宝支付执行业务服务
///
/// 支付方式映射、通道请求组装、通道适配服务调用、支付结果转换
/// TODO Service 当前为占空实现, 后续补全支付执行流程逻辑
///
/// 通过 [AlipayChannelClient] 调用子应用 dax-pay-channel-one 完成支付宝支付下单
/// 请求构建、响应解析全部在本类中完成
@Slf4j
@Service
@RequiredArgsConstructor
public class AlipayPayService {
private static final BigDecimal HUNDRED = new BigDecimal("100");
private final AlipayChannelClient alipayChannelClient;
/// 执行支付宝支付
///
/// @param order 支付订单
@@ -26,7 +37,50 @@ public class AlipayPayService {
/// @param config 通道调用配置(密钥/证书/授权令牌等)
/// @return 支付结果
public PayTradeResultBo pay(PayTrade order, PayParam payParam, Map<String, Object> config) {
// TODO 后续实现: method映射 → 组装ChannelPayReq → channelPayClient.pay → 结果转换
throw new UnsupportedOperationException("AlipayPayService.pay 尚未实现");
// 构建请求
AlipayPayReq req = new AlipayPayReq();
req.setChannel("alipay");
req.setBizOrderNo(payParam.getBizOrderNo());
req.setAmount(payParam.getAmount().multiply(HUNDRED).longValue());
req.setSubject(payParam.getTitle());
req.setDescription(payParam.getDescription());
req.setMethod(payParam.getMethod());
req.setConfig(config);
// 调用子应用
DaxResult<AlipayPayResp> result = alipayChannelClient.pay(req);
if (result.getCode() != 0) {
throw new IllegalStateException("支付宝通道支付失败: " + result.getMsg());
}
return toPayResult(result.getData());
}
/// 解析子应用响应为支付结果 BO
private PayTradeResultBo toPayResult(AlipayPayResp resp) {
PayTradeResultBo bo = new PayTradeResultBo()
.setOutOrderNo(resp.getOutOrderNo())
.setComplete(Boolean.TRUE.equals(resp.getComplete()))
.setPayBody(resp.getPayBody())
.setTransOrderNo(resp.getTransOrderNo());
// 支付参数体类型
String payBodyType = resp.getPayBodyType();
if (payBodyType != null) {
for (PayBodyTypeEnum type : PayBodyTypeEnum.values()) {
if (type.getCode().equals(payBodyType)) {
bo.setPayBodyType(type);
break;
}
}
}
// 完成时间
String finishTime = resp.getFinishTime();
if (finishTime != null && !finishTime.isBlank()) {
bo.setFinishTime(OffsetDateTime.parse(finishTime, DateTimeFormatter.ISO_DATE_TIME));
}
return bo;
}
}

View File

@@ -0,0 +1,20 @@
package cn.daxpay.open.channel.douyin.client;
import cn.daxpay.open.channel.douyin.dto.DouyinPayReq;
import cn.daxpay.open.channel.douyin.dto.DouyinPayResp;
import cn.daxpay.open.payment.common.result.DaxResult;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.service.annotation.HttpExchange;
import org.springframework.web.service.annotation.PostExchange;
/// # 抖音通道客户端
///
/// 声明式 HTTP 接口, 调用子应用 dax-pay-channel-one 的抖音通道接口。
@HttpExchange(accept = MediaType.APPLICATION_JSON_VALUE, contentType = MediaType.APPLICATION_JSON_VALUE)
public interface DouyinChannelClient {
/// 支付下单
@PostExchange("/channel/pay")
DaxResult<DouyinPayResp> pay(@RequestBody DouyinPayReq req);
}

View File

@@ -0,0 +1,35 @@
package cn.daxpay.open.channel.douyin.config;
import cn.daxpay.open.channel.douyin.client.DouyinChannelClient;
import cn.daxpay.open.platform.common.config.properties.DaxpayChannelProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.support.RestClientAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
/// # 抖音通道客户端配置
///
/// 复用全局 [RestClient](由 common-spring 的 RestClientConfiguration 提供, 已预装:
/// OTel traceparent 透传 / BusinessContextInterceptor 业务上下文透传 / Apache HttpClient5 连接池),
/// 经 `mutate()` 派生出绑定 channel-one baseUrl 的实例。
///
/// baseUrl 从 [DaxpayChannelProperties] 统一读取。
@Configuration
public class DouyinClientConfig {
@Bean
public DouyinChannelClient douyinChannelClient(
RestClient restClient,
DaxpayChannelProperties channelProperties) {
// mutate 派生: 继承全局 RestClient 的拦截器 / observation / requestFactory, 仅覆盖 baseUrl
RestClient channelClient = restClient
.mutate()
.baseUrl(channelProperties.getOne().getBaseUrl())
.build();
return HttpServiceProxyFactory
.builderFor(RestClientAdapter.create(channelClient))
.build()
.createClient(DouyinChannelClient.class);
}
}

View File

@@ -0,0 +1,21 @@
package cn.daxpay.open.channel.douyin.dto;
import lombok.Data;
import java.util.Map;
/// # 抖音通道支付请求
///
/// 与子应用 ChannelPayReq 字段一致, 通过 Jackson 序列化传输
@Data
public class DouyinPayReq {
private String channel;
private String bizOrderNo;
private Long amount;
private String subject;
private String description;
private String method;
private String expireTime;
private String otherMethod;
private Map<String, Object> config;
}

View File

@@ -0,0 +1,17 @@
package cn.daxpay.open.channel.douyin.dto;
import lombok.Data;
/// # 抖音通道支付响应
///
/// 与子应用 ChannelPayResp 字段一致
@Data
public class DouyinPayResp {
private String bizOrderNo;
private String outOrderNo;
private String transOrderNo;
private String payBody;
private String payBodyType;
private Boolean complete;
private String finishTime;
}

View File

@@ -1,21 +1,32 @@
package cn.daxpay.open.channel.douyin.strategy;
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
import cn.daxpay.open.channel.douyin.client.DouyinChannelClient;
import cn.daxpay.open.channel.douyin.dto.DouyinPayReq;
import cn.daxpay.open.channel.douyin.dto.DouyinPayResp;
import cn.daxpay.open.payment.common.result.DaxResult;
import cn.daxpay.open.payment.pay.bo.PayTradeResultBo;
import cn.daxpay.open.payment.strategy.pay.AbsPayStrategy;
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Map;
/// # 抖音支付直连支付策略
///
/// 抖音支付直连模式的支付策略(虚类,暂未实现具体支付逻辑)
///
/// 通过 [DouyinChannelClient] 调用子应用 dax-pay-channel-one 完成抖音支付下单
/// TODO 通道配置获取逻辑待补充(需抖音通道配置管理实体)
@Slf4j
@Service
@RequiredArgsConstructor
public class DouyinDirectPayStrategy extends AbsPayStrategy {
private static final BigDecimal HUNDRED = new BigDecimal("100");
private final DouyinChannelClient douyinChannelClient;
@Override
public ProductEnum getProduct() {
return ProductEnum.DOUYIN_PAY;
@@ -23,6 +34,28 @@ public class DouyinDirectPayStrategy extends AbsPayStrategy {
@Override
public PayTradeResultBo doPayHandler() {
throw new UnsupportedOperationException("抖音支付直连暂未实现");
// 构建请求
DouyinPayReq req = new DouyinPayReq();
req.setChannel(ProductEnum.DOUYIN_PAY.getChannel());
req.setBizOrderNo(getPayParam().getBizOrderNo());
req.setAmount(getPayParam().getAmount().multiply(HUNDRED).longValue());
req.setSubject(getPayParam().getTitle());
req.setMethod(getPayParam().getMethod());
// TODO 从数据库获取抖音通道配置
req.setConfig(Map.of());
// 调用子应用
DaxResult<DouyinPayResp> result = douyinChannelClient.pay(req);
if (result.getCode() != 0) {
throw new IllegalStateException("抖音通道支付失败: " + result.getMsg());
}
// 解析响应
DouyinPayResp data = result.getData();
return new PayTradeResultBo()
.setOutOrderNo(data.getOutOrderNo())
.setComplete(Boolean.TRUE.equals(data.getComplete()))
.setPayBody(data.getPayBody())
.setTransOrderNo(data.getTransOrderNo());
}
}

View File

@@ -35,6 +35,14 @@
<artifactId>common-artemis</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 支付宝通道模块 -->
<!-- 提供 AlipayChannelClient (@HttpExchange) 及 AlipayPayReq/AlipayPayResp DTO, 供 Demo 控制器直接调用子应用 -->
<dependency>
<groupId>cn.daxpay.open</groupId>
<artifactId>daxpay-channel-alipay</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,85 @@
package cn.daxpay.open.demo.channel.controller;
import cn.daxpay.open.channel.alipay.client.AlipayChannelClient;
import cn.daxpay.open.channel.alipay.dto.AlipayPayReq;
import cn.daxpay.open.channel.alipay.dto.AlipayPayResp;
import cn.daxpay.open.demo.channel.param.ChannelDemoPayParam;
import cn.daxpay.open.demo.channel.result.ChannelDemoPayResult;
import cn.daxpay.open.platform.core.annotation.IgnoreAuth;
import cn.daxpay.open.platform.core.rest.Res;
import cn.daxpay.open.platform.core.rest.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.Map;
/// # 通道连通性 Demo 接口
///
/// 演示主应用通过 @HttpExchange 客户端调用子应用 dax-pay-channel-one 的完整链路。
/// 前端发起请求 → 主应用构建 AlipayPayReq → AlipayChannelClient 发送 HTTP → 子应用接收并处理 → 响应返回。
///
/// 鉴权: URL 前缀 `/demo/**` 已在白名单, 类上叠加 `@IgnoreAuth` 双保险。
@Slf4j
@IgnoreAuth
@Validated
@Tag(name = "通道连通性演示")
@RestController
@RequestMapping("/demo/channel")
@RequiredArgsConstructor
public class ChannelDemoController {
private static final BigDecimal HUNDRED = new BigDecimal("100");
private final AlipayChannelClient alipayChannelClient;
/// 发起 Demo 支付请求到子应用
///
/// 通过 @HttpExchange 声明式客户端将请求转发到 dax-pay-channel-one 的 `/channel/pay` 端点。
/// config 传空 Map, 子应用进入 Demo 模式返回模拟响应。
@Operation(summary = "发起通道 Demo 支付")
@PostMapping("/pay")
public Result<ChannelDemoPayResult> pay(@Validated @RequestBody ChannelDemoPayParam param) {
log.info("🚀 Demo: 主应用发起通道支付请求, bizOrderNo={}", param.getBizOrderNo());
// 构建通道请求
AlipayPayReq req = new AlipayPayReq();
req.setChannel("alipay");
req.setBizOrderNo(param.getBizOrderNo());
req.setAmount(param.getAmount().multiply(HUNDRED).longValue());
req.setSubject(param.getSubject());
req.setMethod(param.getMethod());
// 空配置 → 子应用进入 Demo 模式
req.setConfig(Map.of());
// 调用子应用 (通过 @HttpExchange, OTel 自动透传 traceId)
var channelResult = alipayChannelClient.pay(req);
if (channelResult.getCode() != 0) {
throw new RuntimeException("通道支付失败: " + channelResult.getMsg());
}
AlipayPayResp resp = channelResult.getData();
// 构建返回结果 (包含双端 traceId 用于链路对照)
ChannelDemoPayResult result = new ChannelDemoPayResult();
result.setBizOrderNo(resp.getBizOrderNo());
result.setOutOrderNo(resp.getOutOrderNo());
result.setPayBody(resp.getPayBody());
result.setPayBodyType(resp.getPayBodyType());
result.setMainAppTraceId(MDC.get("traceId"));
result.setSubAppTraceId(channelResult.getTraceId());
log.info("✅ Demo: 收到子应用响应, outOrderNo={}, subAppTraceId={}",
result.getOutOrderNo(), result.getSubAppTraceId());
return Res.ok(result);
}
}

View File

@@ -0,0 +1,38 @@
package cn.daxpay.open.demo.channel.param;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
/// # 通道连通性 Demo 支付参数
///
/// 前端表单提交的简化参数, 不涉及真实支付订单实体。
@Data
@Schema(description = "通道 Demo 支付参数")
public class ChannelDemoPayParam {
/// 商户订单号
@Schema(description = "商户订单号")
@NotBlank(message = "{validation.field.bizOrderNo.notBlank}")
private String bizOrderNo;
/// 支付金额(元)
@Schema(description = "支付金额(元)")
@NotNull(message = "{validation.field.amount.notNull}")
@DecimalMin(value = "0.01", message = "{validation.field.amount.min}")
private BigDecimal amount;
/// 支付标题
@Schema(description = "支付标题")
@NotBlank(message = "{validation.field.subject.notBlank}")
private String subject;
/// 支付方式(alipay_wap / alipay_app / alipay_page / alipay_qr)
@Schema(description = "支付方式", example = "alipay_qr")
@NotBlank(message = "{validation.field.method.notBlank}")
private String method;
}

View File

@@ -0,0 +1,36 @@
package cn.daxpay.open.demo.channel.result;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/// # 通道连通性 Demo 支付结果
///
/// 展示主应用 → 子应用往返的完整信息, 包含双端 traceId 用于链路对照。
@Data
@Schema(description = "通道 Demo 支付结果")
public class ChannelDemoPayResult {
/// 商户订单号
@Schema(description = "商户订单号")
private String bizOrderNo;
/// 通道侧订单号
@Schema(description = "通道侧订单号")
private String outOrderNo;
/// 支付内容(支付链接 / 二维码 / 表单等)
@Schema(description = "支付内容")
private String payBody;
/// 支付内容类型(qr_code / form / order_id)
@Schema(description = "支付内容类型")
private String payBodyType;
/// 主应用 traceId
@Schema(description = "主应用 traceId")
private String mainAppTraceId;
/// 子应用 traceId
@Schema(description = "子应用 traceId")
private String subAppTraceId;
}

View File

@@ -3,7 +3,7 @@ package cn.daxpay.open.payment.old.pay.channel;
import cn.daxpay.open.payment.old.pay.channel.dto.ChannelPayReq;
import cn.daxpay.open.payment.old.pay.channel.dto.ChannelPayResp;
import cn.daxpay.open.payment.old.pay.channel.dto.ChannelResult;
import cn.daxpay.open.platform.common.config.properties.PlatformCommonProperties;
import cn.daxpay.open.platform.common.config.properties.DaxpayChannelProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
@@ -13,7 +13,7 @@ import org.springframework.web.client.RestClient;
/// # 通道服务 HTTP 客户端
///
/// 封装对通道适配服务(daxpay-channel-one)的 HTTP 调用,统一处理地址拼接、结果解析与异常转换。
/// baseUrl 来自 [PlatformCommonProperties.ChannelOne] 配置。
/// baseUrl 来自 [DaxpayChannelProperties] 配置。
///
@Slf4j
@Component
@@ -21,14 +21,14 @@ import org.springframework.web.client.RestClient;
public class ChannelPayClient {
private final RestClient restClient;
private final PlatformCommonProperties properties;
private final DaxpayChannelProperties channelProperties;
/// 发起支付下单调用
///
/// @param req 通道支付请求
/// @return 通道支付响应
public ChannelPayResp pay(ChannelPayReq req) {
String url = properties.getChannelOne().getBaseUrl() + "/channel/pay";
String url = channelProperties.getOne().getBaseUrl() + "/channel/pay";
ChannelResult<ChannelPayResp> result = restClient.post()
.uri(url)
.body(req)

View File

@@ -0,0 +1,33 @@
package cn.daxpay.open.platform.common.config.properties;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.boot.context.properties.ConfigurationProperties;
/// # 通道适配子应用配置
///
/// 统一管理各通道适配子应用(dax-pay-channel-one/two/...)的连接地址。
/// 各通道模块通过注入本类获取对应子应用的 baseUrl。
@Data
@Accessors(chain = true)
@ConfigurationProperties(prefix = "daxpay.channel")
public class DaxpayChannelProperties {
/// 子应用1(支付宝/微信)
private ChannelApp one = new ChannelApp();
/// 子应用2(银联/拉卡拉) — 未来扩展
private ChannelApp two = new ChannelApp();
/// 子应用3(抖音/其他) — 未来扩展
private ChannelApp three = new ChannelApp();
/// # 子应用连接配置
@Data
@Accessors(chain = true)
public static class ChannelApp {
/// 基础地址
private String baseUrl = "http://127.0.0.1:20100";
}
}

View File

@@ -19,8 +19,6 @@ public class PlatformCommonProperties {
private Spring spring = new Spring();
/// Swagger 配置
private Swagger swagger = new Swagger();
/// 通道适配服务配置
private ChannelOne channelOne = new ChannelOne();
/// # 缓存配置
///
@@ -100,14 +98,6 @@ public class PlatformCommonProperties {
private Integer connectionRequestTimeout = 3;
}
}
/// # 通道适配服务配置
///
@Data
public static class ChannelOne {
/// 通道服务基础地址
private String baseUrl = "http://127.0.0.1:20100";
}
/// # Swagger 配置
///
@Data

View File

@@ -18,6 +18,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- RestClient 声明式 HTTP 客户端(Spring Boot 4 拆为独立 starter, 提供 RestClient.Builder 自动配置 + W3C traceparent 透传) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-restclient</artifactId>
</dependency>
<!-- 切面 -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -9,6 +9,7 @@ import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.util.Timeout;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
@@ -80,12 +81,13 @@ public class RestClientConfiguration {
/// 创建 RestClient Bean
///
/// 使用自动配置的 RestClient.Builder 而非静态 [RestClient.builder]
/// 以便 OTel 拦截器自动注入(W3C traceparent 头自动透传)
/// 优先使用 Spring Boot 自动配置的 RestClient.Builder(携带 OTel 拦截器,
/// 自动透传 W3C traceparent); 若 autoconfiguration 未注册则 fallback 到 [RestClient.builder]
@Bean
public RestClient restClient(RestClient.Builder restClientBuilder,
public RestClient restClient(ObjectProvider<RestClient.Builder> builderProvider,
HttpComponentsClientHttpRequestFactory httpRequestFactory) {
return restClientBuilder
RestClient.Builder builder = builderProvider.getIfAvailable(RestClient::builder);
return builder
.requestFactory(httpRequestFactory)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.requestInterceptor(new BusinessContextInterceptor())