mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-12 07:25:39 +08:00
refactor: 支付宝通道 service 层 findById().orElseThrow() 优化为 existedById,局部变量声明改为 var
This commit is contained in:
@@ -1,24 +1,27 @@
|
||||
-- =====================================================================
|
||||
-- 微信服务商相关表 (DROP + CREATE 重建)
|
||||
-- 支付宝通道相关表 (DROP + CREATE 重建)
|
||||
-- 对应实体:
|
||||
-- org.dromara.daxpay.channel.wechat.entity.app.WechatIsvApp
|
||||
-- org.dromara.daxpay.channel.wechat.entity.config.WechatIsvKeyConfig
|
||||
-- org.dromara.daxpay.channel.wechat.entity.config.WechatIsvAppAuthConfig
|
||||
-- org.dromara.daxpay.channel.wechat.entity.mch.WechatIsvChannelMerchant
|
||||
-- org.dromara.daxpay.channel.alipay.entity.isv.AlipayIsvApp
|
||||
-- org.dromara.daxpay.channel.alipay.entity.isv.AlipayIsvAppKeyConfig
|
||||
-- org.dromara.daxpay.channel.alipay.entity.isv.AlipayIsvAppAuthConfig
|
||||
-- org.dromara.daxpay.channel.alipay.entity.isv.AlipayIsvChannelMerchant
|
||||
-- org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectApp
|
||||
-- org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectAppKeyConfig
|
||||
-- org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectAppAuthConfig
|
||||
-- org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectChannelMerchant
|
||||
-- 执行方式: 手动执行(业务表 DDL 不入库, 由开发者按需在数据库执行)
|
||||
-- 注意: 加密字段(DataEncryptTypeHandler)在数据库层均为普通 text, 加解密在应用层完成
|
||||
-- =====================================================================
|
||||
|
||||
-- =========================
|
||||
-- 1. 微信服务商应用 wechat_isv_app
|
||||
-- 1. 支付宝服务商应用 alipay_isv_app
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."wechat_isv_app";
|
||||
DROP TABLE IF EXISTS "public"."alipay_isv_app";
|
||||
|
||||
CREATE TABLE "public"."wechat_isv_app" (
|
||||
CREATE TABLE "public"."alipay_isv_app" (
|
||||
"id" int8 NOT NULL,
|
||||
"app_name" varchar(64),
|
||||
"app_type" varchar(32),
|
||||
"wx_app_id" varchar(64),
|
||||
"ali_app_id" varchar(64),
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
"last_modifier" int8,
|
||||
@@ -27,41 +30,36 @@ CREATE TABLE "public"."wechat_isv_app" (
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."wechat_isv_app" IS '微信服务商应用';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."app_name" IS '应用名称';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."app_type" IS '应用类型';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."wx_app_id" IS '微信应用AppId';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app"."deleted" IS '逻辑删除标志';
|
||||
COMMENT ON TABLE "public"."alipay_isv_app" IS '支付宝服务商应用';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."app_name" IS '应用名称';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."ali_app_id" IS '支付宝应用ID';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."wechat_isv_app"
|
||||
ADD CONSTRAINT "pk_wechat_isv_app" PRIMARY KEY ("id");
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uk_wechat_isv_app_wx_app_id"
|
||||
ON "public"."wechat_isv_app" ("wx_app_id")
|
||||
WHERE "deleted" = false;
|
||||
ALTER TABLE "public"."alipay_isv_app"
|
||||
ADD CONSTRAINT "pk_alipay_isv_app" PRIMARY KEY ("id");
|
||||
|
||||
|
||||
-- =========================
|
||||
-- 2. 微信服务商密钥配置 wechat_isv_key_config
|
||||
-- 2. 支付宝服务商应用密钥配置 alipay_isv_app_key_config
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."wechat_isv_key_config";
|
||||
DROP TABLE IF EXISTS "public"."alipay_isv_app_key_config";
|
||||
|
||||
CREATE TABLE "public"."wechat_isv_key_config" (
|
||||
CREATE TABLE "public"."alipay_isv_app_key_config" (
|
||||
"id" int8 NOT NULL,
|
||||
"product" varchar(32),
|
||||
"wx_mch_id" varchar(32),
|
||||
"api_key_v3" text,
|
||||
"public_key" text,
|
||||
"public_key_id" varchar(64),
|
||||
"alipay_isv_app_id" int8,
|
||||
"auth_type" varchar(32),
|
||||
"alipay_public_key" text,
|
||||
"private_key" text,
|
||||
"private_cert" text,
|
||||
"cert_serial_no" varchar(128),
|
||||
"app_cert" text,
|
||||
"alipay_cert" text,
|
||||
"alipay_root_cert" text,
|
||||
"secret_key" text,
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
"last_modifier" int8,
|
||||
@@ -70,41 +68,36 @@ CREATE TABLE "public"."wechat_isv_key_config" (
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."wechat_isv_key_config" IS '微信服务商密钥配置';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."product" IS '产品编码';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."wx_mch_id" IS '微信服务商商户号';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."api_key_v3" IS 'APIv3密钥(加密存储)';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."public_key" IS '支付公钥(加密存储)';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."public_key_id" IS '支付公钥ID';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."private_key" IS 'apiclient_key证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."private_cert" IS 'apiclient_cert证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."cert_serial_no" IS '证书序列号';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_key_config"."deleted" IS '逻辑删除标志';
|
||||
COMMENT ON TABLE "public"."alipay_isv_app_key_config" IS '支付宝服务商应用密钥配置';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."alipay_isv_app_id" IS '支付宝服务商应用ID(指向 alipay_isv_app.id)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."auth_type" IS '认证类型';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."alipay_public_key" IS '支付宝公钥';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."private_key" IS '应用私钥(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."app_cert" IS '应用公钥证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."alipay_cert" IS '支付宝公钥证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."alipay_root_cert" IS '支付宝CA根证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."secret_key" IS 'AES通信密钥(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_key_config"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."wechat_isv_key_config"
|
||||
ADD CONSTRAINT "pk_wechat_isv_key_config" PRIMARY KEY ("id");
|
||||
|
||||
-- 密钥配置按产品全局唯一(平台为唯一服务商)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uk_wechat_isv_key_config_product"
|
||||
ON "public"."wechat_isv_key_config" ("product")
|
||||
WHERE "deleted" = false;
|
||||
ALTER TABLE "public"."alipay_isv_app_key_config"
|
||||
ADD CONSTRAINT "pk_alipay_isv_app_key_config" PRIMARY KEY ("id");
|
||||
|
||||
|
||||
-- =========================
|
||||
-- 3. 微信服务商应用授权认证配置 wechat_isv_app_auth_config
|
||||
-- 3. 支付宝服务商应用授权配置 alipay_isv_app_auth_config
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."wechat_isv_app_auth_config";
|
||||
DROP TABLE IF EXISTS "public"."alipay_isv_app_auth_config";
|
||||
|
||||
CREATE TABLE "public"."wechat_isv_app_auth_config" (
|
||||
CREATE TABLE "public"."alipay_isv_app_auth_config" (
|
||||
"id" int8 NOT NULL,
|
||||
"app_id" int8,
|
||||
"app_secret" text,
|
||||
"alipay_isv_app_id" int8,
|
||||
"user_id_type" varchar(32),
|
||||
"auth_callback_url" varchar(255),
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
@@ -114,39 +107,38 @@ CREATE TABLE "public"."wechat_isv_app_auth_config" (
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."wechat_isv_app_auth_config" IS '微信服务商应用授权认证配置';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."app_id" IS '微信服务商应用ID(指向 wechat_isv_app.id)';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."app_secret" IS '应用密钥(加密存储)';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."auth_callback_url" IS '授权回调地址';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."wechat_isv_app_auth_config"."deleted" IS '逻辑删除标志';
|
||||
COMMENT ON TABLE "public"."alipay_isv_app_auth_config" IS '支付宝服务商应用授权配置';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."alipay_isv_app_id" IS '支付宝服务商应用ID(指向 alipay_isv_app.id)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."user_id_type" IS '用户标识类型';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."auth_callback_url" IS '授权回调地址';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_app_auth_config"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."wechat_isv_app_auth_config"
|
||||
ADD CONSTRAINT "pk_wechat_isv_app_auth_config" PRIMARY KEY ("id");
|
||||
|
||||
-- 一个应用只有一条授权认证配置
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uk_wechat_isv_app_auth_config_app_id"
|
||||
ON "public"."wechat_isv_app_auth_config" ("app_id")
|
||||
WHERE "deleted" = false;
|
||||
ALTER TABLE "public"."alipay_isv_app_auth_config"
|
||||
ADD CONSTRAINT "pk_alipay_isv_app_auth_config" PRIMARY KEY ("id");
|
||||
|
||||
|
||||
-- =========================
|
||||
-- 4. 微信服务商通道商户绑定 mch_wechat_isv_channel_merchant
|
||||
-- 微信特约商户关联到服务商本身(服务商密钥全局唯一), 不挂靠具体服务商应用
|
||||
-- 4. 支付宝服务商通道商户绑定 alipay_isv_channel_merchant
|
||||
-- 一条记录代表子商户挂靠在某个服务商应用下的授权关系
|
||||
-- 同一子商户挂不同应用 = 不同行(不同 channel_mch_no)
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."mch_wechat_isv_channel_merchant";
|
||||
DROP TABLE IF EXISTS "public"."mch_alipay_isv_channel_merchant";
|
||||
DROP TABLE IF EXISTS "public"."alipay_isv_channel_merchant";
|
||||
|
||||
CREATE TABLE "public"."mch_wechat_isv_channel_merchant" (
|
||||
CREATE TABLE "public"."alipay_isv_channel_merchant" (
|
||||
"id" int8 NOT NULL,
|
||||
"mch_no" varchar(32) NOT NULL,
|
||||
"channel_mch_no" varchar(64) NOT NULL,
|
||||
"product" varchar(32) NOT NULL,
|
||||
"sub_mch_id" varchar(64) NOT NULL,
|
||||
"isv_app_id" int8,
|
||||
"alipay_user_id" varchar(64),
|
||||
"app_auth_token" varchar(128),
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
"last_modifier" int8,
|
||||
@@ -155,48 +147,37 @@ CREATE TABLE "public"."mch_wechat_isv_channel_merchant" (
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."mch_wechat_isv_channel_merchant" IS '微信服务商通道商户绑定';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."mch_no" IS '商户号';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."channel_mch_no" IS '通道商户号(WISV+雪花)';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."product" IS '所属支付产品';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."sub_mch_id" IS '微信特约商户号/二级商户号(V3 sub_mchid)';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_isv_channel_merchant"."deleted" IS '逻辑删除标志';
|
||||
COMMENT ON TABLE "public"."alipay_isv_channel_merchant" IS '支付宝服务商通道商户绑定';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."mch_no" IS '商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."channel_mch_no" IS '通道商户号(AISV+雪花)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."product" IS '所属支付产品';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."isv_app_id" IS '关联服务商应用ID(指向 alipay_isv_app.id)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."alipay_user_id" IS '子商户支付宝识别码(2088开头的16位数字)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."app_auth_token" IS '应用授权令牌(服务商代子商户调用接口的凭据, 会过期/刷新)';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_isv_channel_merchant"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."mch_wechat_isv_channel_merchant"
|
||||
ADD CONSTRAINT "pk_mch_wechat_isv_channel_merchant" PRIMARY KEY ("id");
|
||||
|
||||
-- 唯一索引: 同一商户下特约商户号不重复(逻辑删除场景排除已删除记录)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uk_wechat_isv_cm_mchno_submch"
|
||||
ON "public"."mch_wechat_isv_channel_merchant" ("mch_no", "sub_mch_id")
|
||||
WHERE "deleted" = false;
|
||||
|
||||
-- 普通索引: 按通道商户号查询
|
||||
CREATE INDEX IF NOT EXISTS "idx_wechat_isv_cm_channel_mch_no"
|
||||
ON "public"."mch_wechat_isv_channel_merchant" ("channel_mch_no");
|
||||
|
||||
-- 普通索引: 按商户号查询
|
||||
CREATE INDEX IF NOT EXISTS "idx_wechat_isv_cm_mch_no"
|
||||
ON "public"."mch_wechat_isv_channel_merchant" ("mch_no");
|
||||
ALTER TABLE "public"."alipay_isv_channel_merchant"
|
||||
ADD CONSTRAINT "pk_alipay_isv_channel_merchant" PRIMARY KEY ("id");
|
||||
|
||||
|
||||
-- =========================
|
||||
-- 5. 微信直连通道商户绑定 mch_wechat_direct_channel_merchant
|
||||
-- 一个微信商户号(wxMchId)对应一个 channelMchNo, 商户的多个应用共享此绑定
|
||||
-- 5. 支付宝直连商户应用 alipay_direct_app
|
||||
-- 每个应用关联一个通道商户号, 拥有独立的支付宝应用ID
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."mch_wechat_direct_channel_merchant";
|
||||
DROP TABLE IF EXISTS "public"."alipay_direct_app";
|
||||
|
||||
CREATE TABLE "public"."mch_wechat_direct_channel_merchant" (
|
||||
CREATE TABLE "public"."alipay_direct_app" (
|
||||
"id" int8 NOT NULL,
|
||||
"mch_no" varchar(32) NOT NULL,
|
||||
"channel_mch_no" varchar(64) NOT NULL,
|
||||
"product" varchar(32) NOT NULL,
|
||||
"wx_mch_id" varchar(32) NOT NULL,
|
||||
"app_name" varchar(64),
|
||||
"ali_app_id" varchar(64),
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
"last_modifier" int8,
|
||||
@@ -205,31 +186,143 @@ CREATE TABLE "public"."mch_wechat_direct_channel_merchant" (
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."mch_wechat_direct_channel_merchant" IS '微信直连通道商户绑定';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."mch_no" IS '商户号';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."channel_mch_no" IS '通道商户号(系统生成雪花号)';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."product" IS '所属支付产品';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."wx_mch_id" IS '微信直连商户号';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."mch_wechat_direct_channel_merchant"."deleted" IS '逻辑删除标志';
|
||||
COMMENT ON TABLE "public"."alipay_direct_app" IS '支付宝直连商户应用';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."mch_no" IS '商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."channel_mch_no" IS '通道商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."app_name" IS '应用名称';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."ali_app_id" IS '支付宝应用ID';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."mch_wechat_direct_channel_merchant"
|
||||
ADD CONSTRAINT "pk_mch_wechat_direct_channel_merchant" PRIMARY KEY ("id");
|
||||
ALTER TABLE "public"."alipay_direct_app"
|
||||
ADD CONSTRAINT "pk_alipay_direct_app" PRIMARY KEY ("id");
|
||||
|
||||
-- 唯一索引: 同一商户下微信商户号不重复(逻辑删除场景排除已删除记录)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uk_wechat_direct_cm_mchno_wxmchid"
|
||||
ON "public"."mch_wechat_direct_channel_merchant" ("mch_no", "wx_mch_id")
|
||||
WHERE "deleted" = false;
|
||||
|
||||
-- 普通索引: 按通道商户号查询
|
||||
CREATE INDEX IF NOT EXISTS "idx_wechat_direct_cm_channel_mch_no"
|
||||
ON "public"."mch_wechat_direct_channel_merchant" ("channel_mch_no");
|
||||
-- =========================
|
||||
-- 6. 支付宝直连商户应用密钥配置 alipay_direct_app_key_config
|
||||
-- 支持公钥模式和证书模式两种认证方式, 敏感字段加密存储
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."alipay_direct_app_key_config";
|
||||
|
||||
-- 普通索引: 按商户号查询
|
||||
CREATE INDEX IF NOT EXISTS "idx_wechat_direct_cm_mch_no"
|
||||
ON "public"."mch_wechat_direct_channel_merchant" ("mch_no");
|
||||
CREATE TABLE "public"."alipay_direct_app_key_config" (
|
||||
"id" int8 NOT NULL,
|
||||
"mch_no" varchar(32) NOT NULL,
|
||||
"channel_mch_no" varchar(64) NOT NULL,
|
||||
"alipay_direct_app_id" int8,
|
||||
"auth_type" varchar(32),
|
||||
"alipay_public_key" text,
|
||||
"private_key" text,
|
||||
"app_cert" text,
|
||||
"alipay_cert" text,
|
||||
"alipay_root_cert" text,
|
||||
"secret_key" text,
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
"last_modifier" int8,
|
||||
"last_modified_time" timestamptz(6),
|
||||
"version" int4 DEFAULT 0 NOT NULL,
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."alipay_direct_app_key_config" IS '支付宝直连商户应用密钥配置';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."mch_no" IS '商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."channel_mch_no" IS '通道商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."alipay_direct_app_id" IS '关联应用ID(指向 alipay_direct_app.id)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."auth_type" IS '认证类型';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."alipay_public_key" IS '支付宝公钥';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."private_key" IS '应用私钥(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."app_cert" IS '应用公钥证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."alipay_cert" IS '支付宝公钥证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."alipay_root_cert" IS '支付宝CA根证书(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."secret_key" IS 'AES通信密钥(加密存储)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_key_config"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."alipay_direct_app_key_config"
|
||||
ADD CONSTRAINT "pk_alipay_direct_app_key_config" PRIMARY KEY ("id");
|
||||
|
||||
|
||||
-- =========================
|
||||
-- 7. 支付宝直连商户应用授权配置 alipay_direct_app_auth_config
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."alipay_direct_app_auth_config";
|
||||
|
||||
CREATE TABLE "public"."alipay_direct_app_auth_config" (
|
||||
"id" int8 NOT NULL,
|
||||
"mch_no" varchar(32) NOT NULL,
|
||||
"channel_mch_no" varchar(64) NOT NULL,
|
||||
"alipay_direct_app_id" int8,
|
||||
"user_id_type" varchar(32),
|
||||
"auth_callback_url" varchar(255),
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
"last_modifier" int8,
|
||||
"last_modified_time" timestamptz(6),
|
||||
"version" int4 DEFAULT 0 NOT NULL,
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."alipay_direct_app_auth_config" IS '支付宝直连商户应用授权配置';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."mch_no" IS '商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."channel_mch_no" IS '通道商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."alipay_direct_app_id" IS '关联应用ID(指向 alipay_direct_app.id)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."user_id_type" IS '用户标识类型';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."auth_callback_url" IS '授权回调地址';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_app_auth_config"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."alipay_direct_app_auth_config"
|
||||
ADD CONSTRAINT "pk_alipay_direct_app_auth_config" PRIMARY KEY ("id");
|
||||
|
||||
|
||||
-- =========================
|
||||
-- 8. 支付宝直连通道商户绑定 alipay_direct_channel_merchant
|
||||
-- 一个商户PID对应一个channelMchNo, 商户的多个应用共享此绑定
|
||||
-- =========================
|
||||
DROP TABLE IF EXISTS "public"."mch_alipay_direct_channel_merchant";
|
||||
DROP TABLE IF EXISTS "public"."alipay_direct_channel_merchant";
|
||||
|
||||
CREATE TABLE "public"."alipay_direct_channel_merchant" (
|
||||
"id" int8 NOT NULL,
|
||||
"mch_no" varchar(32) NOT NULL,
|
||||
"channel_mch_no" varchar(64) NOT NULL,
|
||||
"product" varchar(32) NOT NULL,
|
||||
"alipay_user_id" varchar(64),
|
||||
"creator" int8,
|
||||
"create_time" timestamptz(6),
|
||||
"last_modifier" int8,
|
||||
"last_modified_time" timestamptz(6),
|
||||
"version" int4 DEFAULT 0 NOT NULL,
|
||||
"deleted" bool DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "public"."alipay_direct_channel_merchant" IS '支付宝直连通道商户绑定';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."id" IS '主键';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."mch_no" IS '商户号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."channel_mch_no" IS '通道商户号(系统生成雪花号)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."product" IS '所属支付产品';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."alipay_user_id" IS '支付宝商家唯一识别码(2088开头的16位数字)';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."creator" IS '创建人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."last_modifier" IS '最后修改人';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."last_modified_time" IS '最后修改时间';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."version" IS '乐观锁版本号';
|
||||
COMMENT ON COLUMN "public"."alipay_direct_channel_merchant"."deleted" IS '逻辑删除标志';
|
||||
|
||||
ALTER TABLE "public"."alipay_direct_channel_merchant"
|
||||
ADD CONSTRAINT "pk_alipay_direct_channel_merchant" PRIMARY KEY ("id");
|
||||
|
||||
@@ -108,8 +108,8 @@ public class AlipayDirectAppController {
|
||||
@Operation(summary = "查询应用密钥配置")
|
||||
@GetMapping("/find-key-config-by-app-id")
|
||||
public Result<AlipayDirectAppKeyConfigResult> findKeyConfigByAppId(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long appId) {
|
||||
return Res.ok(alipayDirectAppKeyConfigService.findByAppId(appId));
|
||||
@NotNull(message = "{validation.field.alipayDirectAppId.notNull}") Long alipayDirectAppId) {
|
||||
return Res.ok(alipayDirectAppKeyConfigService.findByAlipayDirectAppId(alipayDirectAppId).toResult());
|
||||
}
|
||||
|
||||
@PermCode(code = "edit", nameCn = "通道商户编辑", nameEn = "Channel Merchant Edit")
|
||||
@@ -124,8 +124,8 @@ public class AlipayDirectAppController {
|
||||
@Operation(summary = "查询应用授权认证配置")
|
||||
@GetMapping("/find-auth-config-by-app-id")
|
||||
public Result<AlipayDirectAppAuthConfigResult> findAuthConfigByAppId(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long appId) {
|
||||
return Res.ok(alipayDirectAppAuthConfigService.findByAppId(appId));
|
||||
@NotNull(message = "{validation.field.alipayDirectAppId.notNull}") Long alipayDirectAppId) {
|
||||
return Res.ok(alipayDirectAppAuthConfigService.findByAlipayDirectAppId(alipayDirectAppId).toResult());
|
||||
}
|
||||
|
||||
@PermCode(code = "edit", nameCn = "通道商户编辑", nameEn = "Channel Merchant Edit")
|
||||
|
||||
@@ -102,8 +102,8 @@ public class AlipayIsvAppController {
|
||||
@Operation(summary = "查询应用密钥配置")
|
||||
@GetMapping("/find-key-config-by-app-id")
|
||||
public Result<AlipayIsvAppKeyConfigResult> findKeyConfigByAppId(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long appId) {
|
||||
return Res.ok(alipayIsvAppKeyConfigService.findByAppId(appId));
|
||||
@NotNull(message = "{validation.field.alipayIsvAppId.notNull}") Long alipayIsvAppId) {
|
||||
return Res.ok(alipayIsvAppKeyConfigService.findByAlipayIsvAppId(alipayIsvAppId).toResult());
|
||||
}
|
||||
|
||||
@PermCode(code = "edit", nameCn = "支付宝服务商编辑", nameEn = "Alipay ISV Edit")
|
||||
@@ -118,8 +118,8 @@ public class AlipayIsvAppController {
|
||||
@Operation(summary = "查询应用授权认证配置")
|
||||
@GetMapping("/find-auth-config-by-app-id")
|
||||
public Result<AlipayIsvAppAuthConfigResult> findAuthConfigByAppId(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long appId) {
|
||||
return Res.ok(alipayIsvAppAuthConfigService.findByAppId(appId));
|
||||
@NotNull(message = "{validation.field.alipayIsvAppId.notNull}") Long alipayIsvAppId) {
|
||||
return Res.ok(alipayIsvAppAuthConfigService.findByAlipayIsvAppId(alipayIsvAppId).toResult());
|
||||
}
|
||||
|
||||
@PermCode(code = "edit", nameCn = "支付宝服务商编辑", nameEn = "Alipay ISV Edit")
|
||||
|
||||
@@ -18,16 +18,16 @@ import java.util.Optional;
|
||||
public class AlipayDirectAppAuthConfigManager extends BaseManager<AlipayDirectAppAuthConfigMapper, AlipayDirectAppAuthConfig> {
|
||||
|
||||
/// 根据应用ID查询授权认证配置
|
||||
public Optional<AlipayDirectAppAuthConfig> findByAppId(Long appId) {
|
||||
public Optional<AlipayDirectAppAuthConfig> findByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
return lambdaQuery()
|
||||
.eq(AlipayDirectAppAuthConfig::getAppId, appId)
|
||||
.eq(AlipayDirectAppAuthConfig::getAlipayDirectAppId, alipayDirectAppId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/// 根据应用ID删除授权认证配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
public void deleteByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
lambdaUpdate()
|
||||
.eq(AlipayDirectAppAuthConfig::getAppId, appId)
|
||||
.eq(AlipayDirectAppAuthConfig::getAlipayDirectAppId, alipayDirectAppId)
|
||||
.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,16 @@ import java.util.Optional;
|
||||
public class AlipayDirectAppKeyConfigManager extends BaseManager<AlipayDirectAppKeyConfigMapper, AlipayDirectAppKeyConfig> {
|
||||
|
||||
/// 根据应用ID查询密钥配置
|
||||
public Optional<AlipayDirectAppKeyConfig> findByAppId(Long appId) {
|
||||
public Optional<AlipayDirectAppKeyConfig> findByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
return lambdaQuery()
|
||||
.eq(AlipayDirectAppKeyConfig::getAppId, appId)
|
||||
.eq(AlipayDirectAppKeyConfig::getAlipayDirectAppId, alipayDirectAppId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/// 根据应用ID删除密钥配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
public void deleteByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
lambdaUpdate()
|
||||
.eq(AlipayDirectAppKeyConfig::getAppId, appId)
|
||||
.eq(AlipayDirectAppKeyConfig::getAlipayDirectAppId, alipayDirectAppId)
|
||||
.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,16 @@ import java.util.Optional;
|
||||
public class AlipayIsvAppAuthConfigManager extends BaseManager<AlipayIsvAppAuthConfigMapper, AlipayIsvAppAuthConfig> {
|
||||
|
||||
/// 根据应用ID查询授权认证配置
|
||||
public Optional<AlipayIsvAppAuthConfig> findByAppId(Long appId) {
|
||||
public Optional<AlipayIsvAppAuthConfig> findByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
return lambdaQuery()
|
||||
.eq(AlipayIsvAppAuthConfig::getAppId, appId)
|
||||
.eq(AlipayIsvAppAuthConfig::getAlipayIsvAppId, alipayIsvAppId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/// 根据应用ID删除授权认证配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
public void deleteByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
lambdaUpdate()
|
||||
.eq(AlipayIsvAppAuthConfig::getAppId, appId)
|
||||
.eq(AlipayIsvAppAuthConfig::getAlipayIsvAppId, alipayIsvAppId)
|
||||
.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,16 @@ import java.util.Optional;
|
||||
public class AlipayIsvAppKeyConfigManager extends BaseManager<AlipayIsvAppKeyConfigMapper, AlipayIsvAppKeyConfig> {
|
||||
|
||||
/// 根据应用ID查询密钥配置
|
||||
public Optional<AlipayIsvAppKeyConfig> findByAppId(Long appId) {
|
||||
public Optional<AlipayIsvAppKeyConfig> findByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
return lambdaQuery()
|
||||
.eq(AlipayIsvAppKeyConfig::getAppId, appId)
|
||||
.eq(AlipayIsvAppKeyConfig::getAlipayIsvAppId, alipayIsvAppId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/// 根据应用ID删除密钥配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
public void deleteByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
lambdaUpdate()
|
||||
.eq(AlipayIsvAppKeyConfig::getAppId, appId)
|
||||
.eq(AlipayIsvAppKeyConfig::getAlipayIsvAppId, alipayIsvAppId)
|
||||
.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public class AlipayDirectAppAuthConfig extends MchBaseEntity implements ToResult
|
||||
|
||||
/// 关联应用ID
|
||||
@TableField(updateStrategy = FieldStrategy.NEVER)
|
||||
private Long appId;
|
||||
private Long alipayDirectAppId;
|
||||
|
||||
/// 用户标识类型
|
||||
private String userIdType;
|
||||
|
||||
@@ -28,7 +28,7 @@ public class AlipayDirectAppKeyConfig extends MchBaseEntity implements ToResult<
|
||||
|
||||
/// 关联应用ID
|
||||
@TableField(updateStrategy = FieldStrategy.NEVER)
|
||||
private Long appId;
|
||||
private Long alipayDirectAppId;
|
||||
|
||||
/// 认证类型
|
||||
private String authType;
|
||||
|
||||
@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName(value = "mch_alipay_direct_channel_merchant", autoResultMap = true)
|
||||
@TableName(value = "alipay_direct_channel_merchant", autoResultMap = true)
|
||||
public class AlipayDirectChannelMerchant extends MchBaseEntity implements ToResult<AlipayDirectChannelMerchantResult> {
|
||||
|
||||
/// 通道商户号(系统生成雪花号)
|
||||
|
||||
@@ -23,7 +23,7 @@ public class AlipayIsvAppAuthConfig extends MpBaseEntity implements ToResult<Ali
|
||||
|
||||
/// 支付宝服务商应用ID
|
||||
@TableField(updateStrategy = FieldStrategy.NEVER)
|
||||
private Long appId;
|
||||
private Long alipayIsvAppId;
|
||||
|
||||
/// 用户标识类型
|
||||
private String userIdType;
|
||||
|
||||
@@ -24,7 +24,7 @@ public class AlipayIsvAppKeyConfig extends MpBaseEntity implements ToResult<Alip
|
||||
|
||||
/// 支付宝服务商应用ID
|
||||
@TableField(updateStrategy = FieldStrategy.NEVER)
|
||||
private Long appId;
|
||||
private Long alipayIsvAppId;
|
||||
|
||||
/// 认证类型
|
||||
private String authType;
|
||||
|
||||
@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName(value = "mch_alipay_isv_channel_merchant", autoResultMap = true)
|
||||
@TableName(value = "alipay_isv_channel_merchant", autoResultMap = true)
|
||||
public class AlipayIsvChannelMerchant extends MchBaseEntity implements ToResult<AlipayIsvChannelMerchantResult> {
|
||||
|
||||
/// 通道商户号(AISV+雪花)
|
||||
|
||||
@@ -16,9 +16,9 @@ import lombok.experimental.Accessors;
|
||||
@Schema(title = "支付宝直连商户应用授权认证配置保存参数")
|
||||
public class AlipayDirectAppAuthConfigParam {
|
||||
|
||||
@NotNull(message = "{validation.field.id.notNull}")
|
||||
@NotNull(message = "{validation.field.alipayDirectAppId.notNull}")
|
||||
@Schema(description = "关联应用ID")
|
||||
private Long appId;
|
||||
private Long alipayDirectAppId;
|
||||
|
||||
@NotBlank(message = "{validation.field.mchNo.notBlank}")
|
||||
@Schema(description = "商户号")
|
||||
|
||||
@@ -15,9 +15,9 @@ import lombok.experimental.Accessors;
|
||||
@Schema(title = "支付宝直连商户应用密钥配置保存参数")
|
||||
public class AlipayDirectAppKeyConfigParam {
|
||||
|
||||
@NotNull(message = "{validation.field.id.notNull}")
|
||||
@NotNull(message = "{validation.field.alipayDirectAppId.notNull}")
|
||||
@Schema(description = "关联应用ID")
|
||||
private Long appId;
|
||||
private Long alipayDirectAppId;
|
||||
|
||||
@NotBlank(message = "{validation.field.mchNo.notBlank}")
|
||||
@Schema(description = "商户号")
|
||||
|
||||
@@ -16,9 +16,9 @@ import lombok.experimental.Accessors;
|
||||
@Schema(title = "支付宝服务商应用授权认证配置保存参数")
|
||||
public class AlipayIsvAppAuthConfigParam {
|
||||
|
||||
@NotNull(message = "{validation.field.id.notNull}")
|
||||
@NotNull(message = "{validation.field.alipayIsvAppId.notNull}")
|
||||
@Schema(description = "支付宝服务商应用ID")
|
||||
private Long appId;
|
||||
private Long alipayIsvAppId;
|
||||
|
||||
@NotBlank(message = "{validation.field.userIdType.notBlank}")
|
||||
@Schema(description = "用户标识类型")
|
||||
|
||||
@@ -15,9 +15,9 @@ import lombok.experimental.Accessors;
|
||||
@Schema(title = "支付宝服务商应用密钥配置保存参数")
|
||||
public class AlipayIsvAppKeyConfigParam {
|
||||
|
||||
@NotNull(message = "{validation.field.id.notNull}")
|
||||
@NotNull(message = "{validation.field.alipayIsvAppId.notNull}")
|
||||
@Schema(description = "支付宝服务商应用ID")
|
||||
private Long appId;
|
||||
private Long alipayIsvAppId;
|
||||
|
||||
@NotBlank(message = "{validation.field.authType.notBlank}")
|
||||
@Schema(description = "认证类型")
|
||||
|
||||
@@ -23,7 +23,7 @@ public class AlipayDirectAppAuthConfigResult extends BaseResult {
|
||||
private String channelMchNo;
|
||||
|
||||
@Schema(description = "关联应用ID")
|
||||
private Long appId;
|
||||
private Long alipayDirectAppId;
|
||||
|
||||
@Schema(description = "用户标识类型")
|
||||
private String userIdType;
|
||||
|
||||
@@ -24,7 +24,7 @@ public class AlipayDirectAppKeyConfigResult extends BaseResult {
|
||||
private String channelMchNo;
|
||||
|
||||
@Schema(description = "关联应用ID")
|
||||
private Long appId;
|
||||
private Long alipayDirectAppId;
|
||||
|
||||
@Schema(description = "认证类型")
|
||||
private String authType;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class AlipayIsvAppAuthConfigResult extends BaseResult {
|
||||
|
||||
/// 支付宝服务商应用ID
|
||||
@Schema(description = "应用ID")
|
||||
private Long appId;
|
||||
private Long alipayIsvAppId;
|
||||
|
||||
/// 用户标识类型
|
||||
@Schema(description = "用户标识类型")
|
||||
|
||||
@@ -18,7 +18,7 @@ public class AlipayIsvAppKeyConfigResult extends BaseResult {
|
||||
|
||||
/// 支付宝服务商应用ID
|
||||
@Schema(description = "应用ID")
|
||||
private Long appId;
|
||||
private Long alipayIsvAppId;
|
||||
|
||||
/// 认证类型
|
||||
@Schema(description = "认证类型")
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
package org.dromara.daxpay.channel.alipay.service.direct;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
|
||||
import org.dromara.daxpay.channel.alipay.convert.direct.AlipayDirectAppAuthConfigConvert;
|
||||
import org.dromara.daxpay.channel.alipay.dao.direct.AlipayDirectAppManager;
|
||||
import org.dromara.daxpay.channel.alipay.dao.direct.AlipayDirectAppAuthConfigManager;
|
||||
import org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectApp;
|
||||
import org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectAppAuthConfig;
|
||||
import org.dromara.daxpay.channel.alipay.param.direct.AlipayDirectAppAuthConfigParam;
|
||||
import org.dromara.daxpay.channel.alipay.result.direct.AlipayDirectAppAuthConfigResult;
|
||||
import org.dromara.daxpay.platform.core.code.CommonErrorCode;
|
||||
import org.dromara.daxpay.platform.core.exception.BizInfoException;
|
||||
import org.dromara.daxpay.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/// # 支付宝直连商户应用授权认证配置
|
||||
///
|
||||
/// 管理直连商户应用的用户授权认证配置,校验应用归属关系后执行新增或更新,校验用户标识类型的合法性。
|
||||
/// 管理直连商户应用的用户授权认证配置,查询时不存在则创建默认记录,保存时校验应用归属关系,校验用户标识类型的合法性。
|
||||
///
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -36,45 +35,42 @@ public class AlipayDirectAppAuthConfigService {
|
||||
private final AlipayDirectAppAuthConfigManager alipayDirectAppAuthConfigManager;
|
||||
private final AlipayDirectAppManager alipayDirectAppManager;
|
||||
|
||||
/// 根据应用ID查询授权认证配置
|
||||
public AlipayDirectAppAuthConfigResult findByAppId(Long appId) {
|
||||
AlipayDirectApp app = alipayDirectAppManager.findById(appId)
|
||||
/// 根据应用ID查询授权认证配置, 不存在则创建默认记录
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AlipayDirectAppAuthConfig findByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
var app = alipayDirectAppManager.findById(alipayDirectAppId)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
return alipayDirectAppAuthConfigManager.findByAppId(appId)
|
||||
.map(AlipayDirectAppAuthConfigConvert.CONVERT::toResult)
|
||||
.orElseGet(() -> new AlipayDirectAppAuthConfigResult()
|
||||
.setAppId(appId)
|
||||
.setMchNo(app.getMchNo())
|
||||
.setChannelMchNo(app.getChannelMchNo())
|
||||
.setUserIdType(AlipayCode.UserIdType.OPENID));
|
||||
var existing = alipayDirectAppAuthConfigManager.findByAlipayDirectAppId(alipayDirectAppId);
|
||||
if (existing.isPresent()) {
|
||||
return existing.get();
|
||||
}
|
||||
var config = new AlipayDirectAppAuthConfig()
|
||||
.setChannelMchNo(app.getChannelMchNo())
|
||||
.setAlipayDirectAppId(alipayDirectAppId)
|
||||
.setUserIdType(AlipayCode.UserIdType.OPENID);
|
||||
config.setMchNo(app.getMchNo());
|
||||
alipayDirectAppAuthConfigManager.save(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
/// 保存应用授权认证配置
|
||||
/// 保存应用授权认证配置(更新)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(AlipayDirectAppAuthConfigParam param) {
|
||||
AlipayDirectApp app = alipayDirectAppManager.findById(param.getAppId())
|
||||
var app = alipayDirectAppManager.findById(param.getAlipayDirectAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
if (!app.getMchNo().equals(param.getMchNo()) || !app.getChannelMchNo().equals(param.getChannelMchNo())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.appNotFound");
|
||||
}
|
||||
this.validateUserIdType(param.getUserIdType());
|
||||
Optional<AlipayDirectAppAuthConfig> existing = alipayDirectAppAuthConfigManager.findByAppId(param.getAppId());
|
||||
if (existing.isPresent()) {
|
||||
AlipayDirectAppAuthConfig config = existing.get();
|
||||
config.setUserIdType(param.getUserIdType());
|
||||
config.setAuthCallbackUrl(param.getAuthCallbackUrl());
|
||||
alipayDirectAppAuthConfigManager.updateById(config);
|
||||
return;
|
||||
}
|
||||
AlipayDirectAppAuthConfig config = AlipayDirectAppAuthConfigConvert.CONVERT.toEntity(param);
|
||||
config.setMchNo(app.getMchNo());
|
||||
config.setChannelMchNo(app.getChannelMchNo());
|
||||
config.setAppId(param.getAppId());
|
||||
alipayDirectAppAuthConfigManager.save(config);
|
||||
var config = this.findByAlipayDirectAppId(param.getAlipayDirectAppId());
|
||||
config.setUserIdType(param.getUserIdType());
|
||||
config.setAuthCallbackUrl(param.getAuthCallbackUrl());
|
||||
alipayDirectAppAuthConfigManager.updateById(config);
|
||||
}
|
||||
|
||||
/// 删除应用授权认证配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
alipayDirectAppAuthConfigManager.deleteByAppId(appId);
|
||||
public void deleteByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
alipayDirectAppAuthConfigManager.deleteByAlipayDirectAppId(alipayDirectAppId);
|
||||
}
|
||||
|
||||
/// 校验用户标识类型
|
||||
|
||||
@@ -7,20 +7,19 @@ import org.dromara.daxpay.channel.alipay.dao.direct.AlipayDirectAppKeyConfigMana
|
||||
import org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectApp;
|
||||
import org.dromara.daxpay.channel.alipay.entity.direct.AlipayDirectAppKeyConfig;
|
||||
import org.dromara.daxpay.channel.alipay.param.direct.AlipayDirectAppKeyConfigParam;
|
||||
import org.dromara.daxpay.channel.alipay.result.direct.AlipayDirectAppKeyConfigResult;
|
||||
import org.dromara.daxpay.platform.core.code.CommonErrorCode;
|
||||
import org.dromara.daxpay.platform.core.exception.BizInfoException;
|
||||
import org.dromara.daxpay.platform.core.exception.DataNotExistException;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/// # 支付宝直连商户应用密钥配置
|
||||
///
|
||||
/// 管理直连商户应用的密钥和证书配置,校验应用归属关系后执行新增或更新,更新时合并敏感字段。
|
||||
/// 管理直连商户应用的密钥和证书配置,查询时不存在则创建默认记录,保存时校验应用归属关系并合并敏感字段。
|
||||
///
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -30,66 +29,40 @@ public class AlipayDirectAppKeyConfigService {
|
||||
private final AlipayDirectAppKeyConfigManager alipayDirectAppKeyConfigManager;
|
||||
private final AlipayDirectAppManager alipayDirectAppManager;
|
||||
|
||||
/// 根据应用ID查询密钥配置
|
||||
public AlipayDirectAppKeyConfigResult findByAppId(Long appId) {
|
||||
AlipayDirectApp app = alipayDirectAppManager.findById(appId)
|
||||
/// 根据应用ID查询密钥配置, 不存在则创建默认记录
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AlipayDirectAppKeyConfig findByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
var app = alipayDirectAppManager.findById(alipayDirectAppId)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
return alipayDirectAppKeyConfigManager.findByAppId(appId)
|
||||
.map(AlipayDirectAppKeyConfigConvert.CONVERT::toResult)
|
||||
.orElseGet(() -> new AlipayDirectAppKeyConfigResult()
|
||||
.setAppId(appId)
|
||||
.setMchNo(app.getMchNo())
|
||||
.setChannelMchNo(app.getChannelMchNo())
|
||||
.setAuthType(AlipayCode.AuthType.AUTH_TYPE_KEY));
|
||||
var existing = alipayDirectAppKeyConfigManager.findByAlipayDirectAppId(alipayDirectAppId);
|
||||
if (existing.isPresent()) {
|
||||
return existing.get();
|
||||
}
|
||||
var config = new AlipayDirectAppKeyConfig()
|
||||
.setChannelMchNo(app.getChannelMchNo())
|
||||
.setAlipayDirectAppId(alipayDirectAppId)
|
||||
.setAuthType(AlipayCode.AuthType.AUTH_TYPE_KEY);
|
||||
config.setMchNo(app.getMchNo());
|
||||
alipayDirectAppKeyConfigManager.save(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
/// 保存应用密钥配置
|
||||
/// 保存应用密钥配置(更新)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(AlipayDirectAppKeyConfigParam param) {
|
||||
AlipayDirectApp app = alipayDirectAppManager.findById(param.getAppId())
|
||||
var app = alipayDirectAppManager.findById(param.getAlipayDirectAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
if (!app.getMchNo().equals(param.getMchNo()) || !app.getChannelMchNo().equals(param.getChannelMchNo())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.appNotFound");
|
||||
}
|
||||
Optional<AlipayDirectAppKeyConfig> existing = alipayDirectAppKeyConfigManager.findByAppId(param.getAppId());
|
||||
if (existing.isPresent()) {
|
||||
AlipayDirectAppKeyConfig config = existing.get();
|
||||
config.setAuthType(param.getAuthType());
|
||||
AlipayDirectAppKeyConfigConvert.CONVERT.copy(param, config);
|
||||
alipayDirectAppKeyConfigManager.updateById(config);
|
||||
return;
|
||||
}
|
||||
this.validateForCreate(param);
|
||||
AlipayDirectAppKeyConfig config = AlipayDirectAppKeyConfigConvert.CONVERT.toEntity(param);
|
||||
config.setMchNo(app.getMchNo());
|
||||
config.setChannelMchNo(app.getChannelMchNo());
|
||||
config.setAppId(param.getAppId());
|
||||
alipayDirectAppKeyConfigManager.save(config);
|
||||
var config = this.findByAlipayDirectAppId(param.getAlipayDirectAppId());
|
||||
config.setAuthType(param.getAuthType());
|
||||
AlipayDirectAppKeyConfigConvert.CONVERT.copy(param, config);
|
||||
alipayDirectAppKeyConfigManager.updateById(config);
|
||||
}
|
||||
|
||||
/// 删除应用密钥配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
alipayDirectAppKeyConfigManager.deleteByAppId(appId);
|
||||
}
|
||||
|
||||
/// 新增时的条件校验
|
||||
private void validateForCreate(AlipayDirectAppKeyConfigParam param) {
|
||||
if (StrUtil.isBlank(param.getPrivateKey())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.privateKeyRequired");
|
||||
}
|
||||
if (AlipayCode.AuthType.AUTH_TYPE_KEY.equals(param.getAuthType())) {
|
||||
if (StrUtil.isBlank(param.getAlipayPublicKey())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.alipayPublicKeyRequired");
|
||||
}
|
||||
} else if (AlipayCode.AuthType.AUTH_TYPE_CERT.equals(param.getAuthType())) {
|
||||
if (StrUtil.isBlank(param.getAppCert())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.appCertRequired");
|
||||
}
|
||||
if (StrUtil.isBlank(param.getAlipayCert())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.alipayCertRequired");
|
||||
}
|
||||
if (StrUtil.isBlank(param.getAlipayRootCert())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.alipayRootCertRequired");
|
||||
}
|
||||
}
|
||||
public void deleteByAlipayDirectAppId(Long alipayDirectAppId) {
|
||||
alipayDirectAppKeyConfigManager.deleteByAlipayDirectAppId(alipayDirectAppId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class AlipayDirectAppService {
|
||||
|
||||
/// 根据商户号和通道商户号查询应用列表
|
||||
public List<AlipayDirectAppResult> listByMchNoAndChannelMchNo(String mchNo, String channelMchNo) {
|
||||
List<AlipayDirectApp> list = alipayDirectAppManager.listByMchNoAndChannelMchNo(mchNo, channelMchNo);
|
||||
var list = alipayDirectAppManager.listByMchNoAndChannelMchNo(mchNo, channelMchNo);
|
||||
return MpUtil.toListResult(list);
|
||||
}
|
||||
|
||||
@@ -55,13 +55,13 @@ public class AlipayDirectAppService {
|
||||
/// 新增支付宝直连商户应用
|
||||
public void add(AlipayDirectAppParam param) {
|
||||
this.assertAliAppIdUnique(param.getMchNo(), param.getChannelMchNo(), param.getAliAppId(), null);
|
||||
AlipayDirectApp entity = AlipayDirectAppConvert.CONVERT.toEntity(param);
|
||||
var entity = AlipayDirectAppConvert.CONVERT.toEntity(param);
|
||||
alipayDirectAppManager.save(entity);
|
||||
}
|
||||
|
||||
/// 更新支付宝直连商户应用
|
||||
public void update(AlipayDirectAppParam param) {
|
||||
AlipayDirectApp entity = alipayDirectAppManager.findById(param.getId())
|
||||
var entity = alipayDirectAppManager.findById(param.getId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
this.assertScopeMatch(entity, param.getMchNo(), param.getChannelMchNo());
|
||||
this.assertAliAppIdUnique(entity.getMchNo(), entity.getChannelMchNo(), param.getAliAppId(), param.getId());
|
||||
@@ -73,8 +73,8 @@ public class AlipayDirectAppService {
|
||||
public void delete(Long id) {
|
||||
alipayDirectAppManager.findById(id)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
alipayDirectAppKeyConfigService.deleteByAppId(id);
|
||||
alipayDirectAppAuthConfigService.deleteByAppId(id);
|
||||
alipayDirectAppKeyConfigService.deleteByAlipayDirectAppId(id);
|
||||
alipayDirectAppAuthConfigService.deleteByAlipayDirectAppId(id);
|
||||
alipayDirectAppManager.deleteById(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class AlipayDirectChannelMerchantService {
|
||||
// 生成通道商户号(雪花号, 不再使用 alipayUserId)
|
||||
String channelMchNo = String.valueOf(IdUtil.getSnowflakeNextId());
|
||||
// 写通用通道商户主表
|
||||
ChannelMerchant channelMerchant = new ChannelMerchant();
|
||||
var channelMerchant = new ChannelMerchant();
|
||||
channelMerchant.setMchNo(param.getMchNo());
|
||||
channelMerchant.setChannelMchNo(channelMchNo);
|
||||
channelMerchant.setChannelMerchantName(param.getChannelMerchantName());
|
||||
@@ -48,7 +48,7 @@ public class AlipayDirectChannelMerchantService {
|
||||
channelMerchant.setEnable(true);
|
||||
channelMerchantManager.save(channelMerchant);
|
||||
// 写直连绑定表(alipayUserId 作为业务字段, 不参与关联)
|
||||
AlipayDirectChannelMerchant entity = new AlipayDirectChannelMerchant();
|
||||
var entity = new AlipayDirectChannelMerchant();
|
||||
entity.setMchNo(param.getMchNo());
|
||||
entity.setChannelMchNo(channelMchNo);
|
||||
entity.setProduct(param.getProduct());
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
package org.dromara.daxpay.channel.alipay.service.isv;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
|
||||
import org.dromara.daxpay.channel.alipay.convert.isv.AlipayIsvAppAuthConfigConvert;
|
||||
import org.dromara.daxpay.channel.alipay.dao.isv.AlipayIsvAppManager;
|
||||
import org.dromara.daxpay.channel.alipay.dao.isv.AlipayIsvAppAuthConfigManager;
|
||||
import org.dromara.daxpay.channel.alipay.entity.isv.AlipayIsvAppAuthConfig;
|
||||
import org.dromara.daxpay.channel.alipay.param.isv.AlipayIsvAppAuthConfigParam;
|
||||
import org.dromara.daxpay.channel.alipay.result.isv.AlipayIsvAppAuthConfigResult;
|
||||
import org.dromara.daxpay.platform.core.code.CommonErrorCode;
|
||||
import org.dromara.daxpay.platform.core.exception.BizInfoException;
|
||||
import org.dromara.daxpay.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/// # 支付宝服务商应用授权认证配置
|
||||
///
|
||||
/// 管理服务商应用的用户授权认证配置,包括用户标识类型的合法性校验(仅支持openid/userid/openid_userid)。
|
||||
/// 管理服务商应用的用户授权认证配置,查询时不存在则创建默认记录,包括用户标识类型的合法性校验(仅支持openid/userid/openid_userid)。
|
||||
///
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -35,38 +34,36 @@ public class AlipayIsvAppAuthConfigService {
|
||||
private final AlipayIsvAppAuthConfigManager alipayIsvAppAuthConfigManager;
|
||||
private final AlipayIsvAppManager alipayIsvAppManager;
|
||||
|
||||
/// 根据应用ID查询授权认证配置
|
||||
public AlipayIsvAppAuthConfigResult findByAppId(Long appId) {
|
||||
alipayIsvAppManager.findById(appId)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
return alipayIsvAppAuthConfigManager.findByAppId(appId)
|
||||
.map(AlipayIsvAppAuthConfigConvert.CONVERT::toResult)
|
||||
.orElseGet(() -> new AlipayIsvAppAuthConfigResult()
|
||||
.setAppId(appId)
|
||||
.setUserIdType(AlipayCode.UserIdType.OPENID));
|
||||
/// 根据应用ID查询授权认证配置, 不存在则创建默认记录
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AlipayIsvAppAuthConfig findByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
if (!alipayIsvAppManager.existedById(alipayIsvAppId)) {
|
||||
throw new DataNotExistException("error.channel.alipay.appNotFound");
|
||||
}
|
||||
var existing = alipayIsvAppAuthConfigManager.findByAlipayIsvAppId(alipayIsvAppId);
|
||||
if (existing.isPresent()) {
|
||||
return existing.get();
|
||||
}
|
||||
var config = new AlipayIsvAppAuthConfig()
|
||||
.setAlipayIsvAppId(alipayIsvAppId)
|
||||
.setUserIdType(AlipayCode.UserIdType.OPENID);
|
||||
alipayIsvAppAuthConfigManager.save(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
/// 保存应用授权认证配置
|
||||
/// 保存应用授权认证配置(更新)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(AlipayIsvAppAuthConfigParam param) {
|
||||
alipayIsvAppManager.findById(param.getAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
this.validateUserIdType(param.getUserIdType());
|
||||
Optional<AlipayIsvAppAuthConfig> existing = alipayIsvAppAuthConfigManager.findByAppId(param.getAppId());
|
||||
if (existing.isPresent()) {
|
||||
AlipayIsvAppAuthConfig config = existing.get();
|
||||
config.setUserIdType(param.getUserIdType());
|
||||
config.setAuthCallbackUrl(param.getAuthCallbackUrl());
|
||||
alipayIsvAppAuthConfigManager.updateById(config);
|
||||
return;
|
||||
}
|
||||
AlipayIsvAppAuthConfig config = AlipayIsvAppAuthConfigConvert.CONVERT.toEntity(param);
|
||||
config.setAppId(param.getAppId());
|
||||
alipayIsvAppAuthConfigManager.save(config);
|
||||
var config = this.findByAlipayIsvAppId(param.getAlipayIsvAppId());
|
||||
config.setUserIdType(param.getUserIdType());
|
||||
config.setAuthCallbackUrl(param.getAuthCallbackUrl());
|
||||
alipayIsvAppAuthConfigManager.updateById(config);
|
||||
}
|
||||
|
||||
/// 删除应用授权认证配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
alipayIsvAppAuthConfigManager.deleteByAppId(appId);
|
||||
public void deleteByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
alipayIsvAppAuthConfigManager.deleteByAlipayIsvAppId(alipayIsvAppId);
|
||||
}
|
||||
|
||||
/// 校验用户标识类型
|
||||
|
||||
@@ -6,20 +6,17 @@ import org.dromara.daxpay.channel.alipay.dao.isv.AlipayIsvAppManager;
|
||||
import org.dromara.daxpay.channel.alipay.dao.isv.AlipayIsvAppKeyConfigManager;
|
||||
import org.dromara.daxpay.channel.alipay.entity.isv.AlipayIsvAppKeyConfig;
|
||||
import org.dromara.daxpay.channel.alipay.param.isv.AlipayIsvAppKeyConfigParam;
|
||||
import org.dromara.daxpay.channel.alipay.result.isv.AlipayIsvAppKeyConfigResult;
|
||||
import org.dromara.daxpay.platform.core.code.CommonErrorCode;
|
||||
import org.dromara.daxpay.platform.core.exception.BizInfoException;
|
||||
import org.dromara.daxpay.platform.core.exception.DataNotExistException;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/// # 支付宝服务商应用密钥配置
|
||||
///
|
||||
/// 管理服务商应用的密钥和证书配置,支持新增和更新操作,更新时合并敏感字段(空值表示不修改)。
|
||||
/// 管理服务商应用的密钥和证书配置,查询时不存在则创建默认记录,保存时合并敏感字段(空值表示不修改)。
|
||||
///
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -29,59 +26,34 @@ public class AlipayIsvAppKeyConfigService {
|
||||
private final AlipayIsvAppKeyConfigManager alipayIsvAppKeyConfigManager;
|
||||
private final AlipayIsvAppManager alipayIsvAppManager;
|
||||
|
||||
/// 根据应用ID查询密钥配置
|
||||
public AlipayIsvAppKeyConfigResult findByAppId(Long appId) {
|
||||
alipayIsvAppManager.findById(appId)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
return alipayIsvAppKeyConfigManager.findByAppId(appId)
|
||||
.map(AlipayIsvAppKeyConfigConvert.CONVERT::toResult)
|
||||
.orElseGet(() -> new AlipayIsvAppKeyConfigResult()
|
||||
.setAppId(appId)
|
||||
.setAuthType(AlipayCode.AuthType.AUTH_TYPE_KEY));
|
||||
/// 根据应用ID查询密钥配置, 不存在则创建默认记录
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AlipayIsvAppKeyConfig findByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
if (!alipayIsvAppManager.existedById(alipayIsvAppId)) {
|
||||
throw new DataNotExistException("error.channel.alipay.appNotFound");
|
||||
}
|
||||
var existing = alipayIsvAppKeyConfigManager.findByAlipayIsvAppId(alipayIsvAppId);
|
||||
if (existing.isPresent()) {
|
||||
return existing.get();
|
||||
}
|
||||
var config = new AlipayIsvAppKeyConfig()
|
||||
.setAlipayIsvAppId(alipayIsvAppId)
|
||||
.setAuthType(AlipayCode.AuthType.AUTH_TYPE_KEY);
|
||||
alipayIsvAppKeyConfigManager.save(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
/// 保存应用密钥配置
|
||||
/// 保存应用密钥配置(更新)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(AlipayIsvAppKeyConfigParam param) {
|
||||
alipayIsvAppManager.findById(param.getAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
Optional<AlipayIsvAppKeyConfig> existing = alipayIsvAppKeyConfigManager.findByAppId(param.getAppId());
|
||||
if (existing.isPresent()) {
|
||||
AlipayIsvAppKeyConfig config = existing.get();
|
||||
config.setAuthType(param.getAuthType());
|
||||
AlipayIsvAppKeyConfigConvert.CONVERT.copy(param, config);
|
||||
alipayIsvAppKeyConfigManager.updateById(config);
|
||||
return;
|
||||
}
|
||||
this.validateForCreate(param);
|
||||
AlipayIsvAppKeyConfig config = AlipayIsvAppKeyConfigConvert.CONVERT.toEntity(param);
|
||||
config.setAppId(param.getAppId());
|
||||
alipayIsvAppKeyConfigManager.save(config);
|
||||
AlipayIsvAppKeyConfig config = this.findByAlipayIsvAppId(param.getAlipayIsvAppId());
|
||||
config.setAuthType(param.getAuthType());
|
||||
AlipayIsvAppKeyConfigConvert.CONVERT.copy(param, config);
|
||||
alipayIsvAppKeyConfigManager.updateById(config);
|
||||
}
|
||||
|
||||
/// 删除应用密钥配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
alipayIsvAppKeyConfigManager.deleteByAppId(appId);
|
||||
}
|
||||
|
||||
/// 新增时的条件校验
|
||||
private void validateForCreate(AlipayIsvAppKeyConfigParam param) {
|
||||
if (StrUtil.isBlank(param.getPrivateKey())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.privateKeyRequired");
|
||||
}
|
||||
if (AlipayCode.AuthType.AUTH_TYPE_KEY.equals(param.getAuthType())) {
|
||||
if (StrUtil.isBlank(param.getAlipayPublicKey())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.alipayPublicKeyRequired");
|
||||
}
|
||||
} else if (AlipayCode.AuthType.AUTH_TYPE_CERT.equals(param.getAuthType())) {
|
||||
if (StrUtil.isBlank(param.getAppCert())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.appCertRequired");
|
||||
}
|
||||
if (StrUtil.isBlank(param.getAlipayCert())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.alipayCertRequired");
|
||||
}
|
||||
if (StrUtil.isBlank(param.getAlipayRootCert())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.alipay.alipayRootCertRequired");
|
||||
}
|
||||
}
|
||||
public void deleteByAlipayIsvAppId(Long alipayIsvAppId) {
|
||||
alipayIsvAppKeyConfigManager.deleteByAlipayIsvAppId(alipayIsvAppId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class AlipayIsvAppService {
|
||||
|
||||
/// 查询全部应用列表
|
||||
public List<AlipayIsvAppResult> listAll() {
|
||||
List<AlipayIsvApp> list = alipayIsvAppManager.listAll();
|
||||
var list = alipayIsvAppManager.listAll();
|
||||
return MpUtil.toListResult(list);
|
||||
}
|
||||
|
||||
@@ -55,13 +55,13 @@ public class AlipayIsvAppService {
|
||||
/// 新增支付宝服务商应用
|
||||
public void add(AlipayIsvAppParam param) {
|
||||
this.assertAliAppIdUnique(param.getAliAppId(), null);
|
||||
AlipayIsvApp entity = AlipayIsvAppConvert.CONVERT.toEntity(param);
|
||||
var entity = AlipayIsvAppConvert.CONVERT.toEntity(param);
|
||||
alipayIsvAppManager.save(entity);
|
||||
}
|
||||
|
||||
/// 更新支付宝服务商应用
|
||||
public void update(AlipayIsvAppParam param) {
|
||||
AlipayIsvApp entity = alipayIsvAppManager.findById(param.getId())
|
||||
var entity = alipayIsvAppManager.findById(param.getId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
this.assertAliAppIdUnique(param.getAliAppId(), param.getId());
|
||||
AlipayIsvAppConvert.CONVERT.copy(param, entity);
|
||||
@@ -72,8 +72,8 @@ public class AlipayIsvAppService {
|
||||
public void delete(Long id) {
|
||||
alipayIsvAppManager.findById(id)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
alipayIsvAppKeyConfigService.deleteByAppId(id);
|
||||
alipayIsvAppAuthConfigService.deleteByAppId(id);
|
||||
alipayIsvAppKeyConfigService.deleteByAlipayIsvAppId(id);
|
||||
alipayIsvAppAuthConfigService.deleteByAlipayIsvAppId(id);
|
||||
alipayIsvAppManager.deleteById(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class AlipayIsvChannelMerchantService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void create(AlipayIsvChannelMerchantCreateParam param) {
|
||||
// 校验服务商应用存在(用 isvAppId 系统主键查询)
|
||||
AlipayIsvApp isvApp = alipayIsvAppManager.findById(param.getIsvAppId())
|
||||
var isvApp = alipayIsvAppManager.findById(param.getIsvAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
// 校验同一应用下子商户号不重复
|
||||
if (alipayIsvChannelMerchantManager.existsByIsvAppIdAndAlipayUserId(
|
||||
@@ -45,7 +45,7 @@ public class AlipayIsvChannelMerchantService {
|
||||
// 生成通道商户号:前缀 AISV + 雪花ID(无分隔符, 符合 TradeNoGenerateUtil 约定)
|
||||
String channelMchNo = "AISV" + IdUtil.getSnowflakeNextId();
|
||||
// 写通用通道商户主表
|
||||
ChannelMerchant channelMerchant = new ChannelMerchant();
|
||||
var channelMerchant = new ChannelMerchant();
|
||||
channelMerchant.setMchNo(param.getMchNo());
|
||||
channelMerchant.setChannelMchNo(channelMchNo);
|
||||
channelMerchant.setChannelMerchantName(param.getChannelMerchantName());
|
||||
@@ -54,7 +54,7 @@ public class AlipayIsvChannelMerchantService {
|
||||
channelMerchant.setEnable(true);
|
||||
channelMerchantManager.save(channelMerchant);
|
||||
// 写服务商绑定表(含挂靠关系专属字段)
|
||||
AlipayIsvChannelMerchant entity = new AlipayIsvChannelMerchant();
|
||||
var entity = new AlipayIsvChannelMerchant();
|
||||
entity.setMchNo(param.getMchNo());
|
||||
entity.setChannelMchNo(channelMchNo);
|
||||
entity.setProduct(param.getProduct());
|
||||
|
||||
@@ -96,8 +96,8 @@ public class WechatIsvAppController {
|
||||
@Operation(summary = "查询应用授权认证配置")
|
||||
@GetMapping("/find-auth-config-by-app-id")
|
||||
public Result<WechatIsvAppAuthConfigResult> findAuthConfigByAppId(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long appId) {
|
||||
return Res.ok(wechatIsvAppAuthConfigService.findByAppId(appId));
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long wechatIsvAppId) {
|
||||
return Res.ok(wechatIsvAppAuthConfigService.findByWechatIsvAppId(wechatIsvAppId));
|
||||
}
|
||||
|
||||
@PermCode(code = "edit", nameCn = "微信服务商编辑", nameEn = "WeChat ISV Edit")
|
||||
|
||||
@@ -16,16 +16,16 @@ import java.util.Optional;
|
||||
public class WechatIsvAppAuthConfigManager extends BaseManager<WechatIsvAppAuthConfigMapper, WechatIsvAppAuthConfig> {
|
||||
|
||||
/// 根据应用ID查询授权认证配置
|
||||
public Optional<WechatIsvAppAuthConfig> findByAppId(Long appId) {
|
||||
public Optional<WechatIsvAppAuthConfig> findByWechatIsvAppId(Long wechatIsvAppId) {
|
||||
return lambdaQuery()
|
||||
.eq(WechatIsvAppAuthConfig::getAppId, appId)
|
||||
.eq(WechatIsvAppAuthConfig::getWechatIsvAppId, wechatIsvAppId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/// 根据应用ID删除授权认证配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
public void deleteByWechatIsvAppId(Long wechatIsvAppId) {
|
||||
lambdaUpdate()
|
||||
.eq(WechatIsvAppAuthConfig::getAppId, appId)
|
||||
.eq(WechatIsvAppAuthConfig::getWechatIsvAppId, wechatIsvAppId)
|
||||
.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class WechatIsvAppAuthConfig extends MpBaseEntity implements ToResult<Wec
|
||||
|
||||
/// 微信服务商应用ID
|
||||
@TableField(updateStrategy = FieldStrategy.NEVER)
|
||||
private Long appId;
|
||||
private Long wechatIsvAppId;
|
||||
|
||||
/// 应用密钥(加密存储)
|
||||
@TableField(typeHandler = DataEncryptTypeHandler.class)
|
||||
|
||||
@@ -15,7 +15,7 @@ public class WechatIsvAppAuthConfigParam {
|
||||
|
||||
@NotNull(message = "{validation.field.id.notNull}")
|
||||
@Schema(description = "微信服务商应用ID")
|
||||
private Long appId;
|
||||
private Long wechatIsvAppId;
|
||||
|
||||
@Schema(description = "应用密钥(加密存储),所有应用类型首次保存时必填")
|
||||
private String appSecret;
|
||||
|
||||
@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
|
||||
public class WechatIsvAppAuthConfigResult extends BaseResult {
|
||||
|
||||
@Schema(description = "微信服务商应用ID")
|
||||
private Long appId;
|
||||
private Long wechatIsvAppId;
|
||||
|
||||
@SensitiveInfo(front = 12, end = 12)
|
||||
@Schema(description = "应用密钥(加密存储)")
|
||||
|
||||
@@ -30,24 +30,24 @@ public class WechatIsvAppAuthConfigService {
|
||||
private final WechatIsvAppManager wechatIsvAppManager;
|
||||
|
||||
/// 根据应用ID查询授权认证配置
|
||||
public WechatIsvAppAuthConfigResult findByAppId(Long appId) {
|
||||
WechatIsvApp app = wechatIsvAppManager.findById(appId)
|
||||
public WechatIsvAppAuthConfigResult findByWechatIsvAppId(Long wechatIsvAppId) {
|
||||
WechatIsvApp app = wechatIsvAppManager.findById(wechatIsvAppId)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.wechat.appNotFound"));
|
||||
return wechatIsvAppAuthConfigManager.findByAppId(appId)
|
||||
return wechatIsvAppAuthConfigManager.findByWechatIsvAppId(wechatIsvAppId)
|
||||
.map(config -> WechatIsvAppAuthConfigConvert.CONVERT.toResult(config)
|
||||
.setAppSecretConfigured(StrUtil.isNotBlank(config.getAppSecret())))
|
||||
.orElseGet(() -> new WechatIsvAppAuthConfigResult()
|
||||
.setAppId(appId)
|
||||
.setWechatIsvAppId(wechatIsvAppId)
|
||||
.setAppSecretConfigured(false));
|
||||
}
|
||||
|
||||
/// 保存应用授权认证配置
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(WechatIsvAppAuthConfigParam param) {
|
||||
WechatIsvApp app = wechatIsvAppManager.findById(param.getAppId())
|
||||
WechatIsvApp app = wechatIsvAppManager.findById(param.getWechatIsvAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.wechat.appNotFound"));
|
||||
String authCallbackUrl = this.resolveAuthCallbackUrl(app, param.getAuthCallbackUrl());
|
||||
Optional<WechatIsvAppAuthConfig> existing = wechatIsvAppAuthConfigManager.findByAppId(param.getAppId());
|
||||
Optional<WechatIsvAppAuthConfig> existing = wechatIsvAppAuthConfigManager.findByWechatIsvAppId(param.getWechatIsvAppId());
|
||||
if (existing.isPresent()) {
|
||||
WechatIsvAppAuthConfig config = existing.get();
|
||||
WechatIsvAppAuthConfigConvert.CONVERT.copy(param, config);
|
||||
@@ -63,7 +63,7 @@ public class WechatIsvAppAuthConfigService {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.wechat.appSecretRequired");
|
||||
}
|
||||
WechatIsvAppAuthConfig config = WechatIsvAppAuthConfigConvert.CONVERT.toEntity(param);
|
||||
config.setAppId(param.getAppId());
|
||||
config.setWechatIsvAppId(param.getWechatIsvAppId());
|
||||
config.setAuthCallbackUrl(authCallbackUrl);
|
||||
wechatIsvAppAuthConfigManager.save(config);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ public class WechatIsvAppAuthConfigService {
|
||||
}
|
||||
|
||||
/// 删除应用授权认证配置
|
||||
public void deleteByAppId(Long appId) {
|
||||
wechatIsvAppAuthConfigManager.deleteByAppId(appId);
|
||||
public void deleteByWechatIsvAppId(Long wechatIsvAppId) {
|
||||
wechatIsvAppAuthConfigManager.deleteByWechatIsvAppId(wechatIsvAppId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class WechatIsvAppService {
|
||||
public void delete(Long id) {
|
||||
wechatIsvAppManager.findById(id)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.wechat.appNotFound"));
|
||||
wechatIsvAppAuthConfigService.deleteByAppId(id);
|
||||
wechatIsvAppAuthConfigService.deleteByWechatIsvAppId(id);
|
||||
wechatIsvAppManager.deleteById(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ import org.springframework.stereotype.Service;
|
||||
public class WechatMiniAuthService {
|
||||
|
||||
/// 获取微信AccessToken数据
|
||||
public AuthResult getOpenId(String authCode, String appId, String appSecret){
|
||||
var wxMaService = this.getWxMaService(appId,appSecret);
|
||||
public AuthResult getOpenId(String authCode, String wxAppId, String appSecret){
|
||||
var wxMaService = this.getWxMaService(wxAppId,appSecret);
|
||||
WxMaJscode2SessionResult sessionResult;
|
||||
try {
|
||||
sessionResult = wxMaService.jsCode2SessionInfo(authCode);
|
||||
@@ -34,11 +34,11 @@ public class WechatMiniAuthService {
|
||||
}
|
||||
|
||||
/// 获取微信小程序API的Service
|
||||
public WxMaService getWxMaService(String appId, String appSecret) {
|
||||
public WxMaService getWxMaService(String wxAppId, String appSecret) {
|
||||
WxMaService wxMaService = new WxMaServiceImpl();
|
||||
var wxMpConfig = new WxMaDefaultConfigImpl();
|
||||
// 设置微信小程序的appid
|
||||
wxMpConfig.setAppid(appId);
|
||||
wxMpConfig.setAppid(wxAppId);
|
||||
// 设置微信小程序的app corpSecret
|
||||
wxMpConfig.setSecret(appSecret);
|
||||
try {
|
||||
|
||||
@@ -48,8 +48,8 @@ public class WechatOpenAuthService {
|
||||
}
|
||||
|
||||
/// 获取微信AccessToken数据
|
||||
public AuthResult getTokenAndOpenId(String authCode, String appId, String appSecret){
|
||||
WxMpService wxMpService = this.getWxMpService(appId,appSecret);
|
||||
public AuthResult getTokenAndOpenId(String authCode, String wxAppId, String appSecret){
|
||||
WxMpService wxMpService = this.getWxMpService(wxAppId,appSecret);
|
||||
WxOAuth2AccessToken accessToken;
|
||||
try {
|
||||
accessToken = wxMpService.getOAuth2Service().getAccessToken(authCode);
|
||||
@@ -63,11 +63,11 @@ public class WechatOpenAuthService {
|
||||
}
|
||||
|
||||
/// 获取微信公众号API的Service
|
||||
private WxMpService getWxMpService(String appId, String appSecret) {
|
||||
private WxMpService getWxMpService(String wxAppId, String appSecret) {
|
||||
WxMpService wxMpService = new WxMpServiceImpl();
|
||||
WxMpDefaultConfigImpl wxMpConfig = new WxMpDefaultConfigImpl();
|
||||
// 设置微信公众号的appid
|
||||
wxMpConfig.setAppId(appId);
|
||||
wxMpConfig.setAppId(wxAppId);
|
||||
// 设置微信公众号的app corpSecret
|
||||
wxMpConfig.setSecret(appSecret);
|
||||
try {
|
||||
|
||||
@@ -25,7 +25,7 @@ public class WechatConfig extends MpBaseEntity implements ToResult<WechatConfigR
|
||||
|
||||
/// 微信公众号AppId
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
private String appId;
|
||||
private String wxAppId;
|
||||
|
||||
/// 微信公众号AppSecret
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
|
||||
@@ -15,7 +15,7 @@ public class WechatConfigParam {
|
||||
private String qrcode;
|
||||
|
||||
@Schema(description = "微信公众号AppId")
|
||||
private String appId;
|
||||
private String wxAppId;
|
||||
|
||||
@Schema(description = "微信公众号AppSecret")
|
||||
private String appSecret;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class WechatConfigResult extends BaseResult {
|
||||
private String qrcode;
|
||||
|
||||
@Schema(description = "微信公众号AppId")
|
||||
private String appId;
|
||||
private String wxAppId;
|
||||
|
||||
@Schema(description = "微信公众号AppSecret")
|
||||
private String appSecret;
|
||||
|
||||
@@ -50,5 +50,5 @@ public class WechatMessageRecord extends MpBaseEntity {
|
||||
private String scene;
|
||||
|
||||
/// 使用的AppId(用于多副本部署时区分不同配置)
|
||||
private String appId;
|
||||
private String wxAppId;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.Map;
|
||||
public class TemplateMessageParam {
|
||||
|
||||
/// 公众号AppId
|
||||
private String appId;
|
||||
private String wxAppId;
|
||||
|
||||
/// 公众号AppSecret
|
||||
private String appSecret;
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.Map;
|
||||
public class UniformMessageParam {
|
||||
|
||||
/// 小程序AppId
|
||||
private String appId;
|
||||
private String wxAppId;
|
||||
|
||||
/// 小程序AppSecret
|
||||
private String appSecret;
|
||||
|
||||
@@ -40,7 +40,7 @@ public class WechatMaMessageService {
|
||||
/// @return 消息发送结果
|
||||
public MessageSendResult sendUniformMessage(UniformMessageParam param) {
|
||||
// 验证配置参数
|
||||
validateConfig(param.getAppId(), param.getAppSecret());
|
||||
validateConfig(param.getWxAppId(), param.getAppSecret());
|
||||
|
||||
// 创建消息记录
|
||||
WechatMessageRecord record = createMessageRecord(param);
|
||||
@@ -52,13 +52,13 @@ public class WechatMaMessageService {
|
||||
|
||||
try {
|
||||
// 获取AccessToken
|
||||
String accessToken = tokenService.getAccessToken(param.getAppId(), param.getAppSecret());
|
||||
String accessToken = tokenService.getAccessToken(param.getWxAppId(), param.getAppSecret());
|
||||
|
||||
// 构建统一服务消息
|
||||
WxMaUniformMessage uniformMessage = buildUniformMessage(param);
|
||||
|
||||
// 创建微信小程序服务
|
||||
WxMaService wxMaService = createWxMaService(param.getAppId(), param.getAppSecret(), accessToken);
|
||||
WxMaService wxMaService = createWxMaService(param.getWxAppId(), param.getAppSecret(), accessToken);
|
||||
|
||||
// 发送消息
|
||||
wxMaService.getMsgService().sendUniformMsg(uniformMessage);
|
||||
@@ -148,9 +148,9 @@ public class WechatMaMessageService {
|
||||
}
|
||||
|
||||
/// 验证配置参数
|
||||
private void validateConfig(String appId, String appSecret) {
|
||||
if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) {
|
||||
log.error("微信配置参数为空,appId: {}", appId);
|
||||
private void validateConfig(String wxAppId, String appSecret) {
|
||||
if (StrUtil.isBlank(wxAppId) || StrUtil.isBlank(appSecret)) {
|
||||
log.error("微信配置参数为空,wxAppId: {}", wxAppId);
|
||||
throw new OperationFailException(CommonCode.FAIL_CODE, "error.payment.channel.微信配置参数不能为空");
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ public class WechatMaMessageService {
|
||||
record.setStatus("sending");
|
||||
record.setSendTime(OffsetDateTime.now(ZoneOffset.UTC));
|
||||
record.setScene(param.getScene());
|
||||
record.setAppId(param.getAppId());
|
||||
record.setWxAppId(param.getWxAppId());
|
||||
return record;
|
||||
}
|
||||
|
||||
@@ -188,10 +188,10 @@ public class WechatMaMessageService {
|
||||
}
|
||||
|
||||
/// 创建微信小程序Service
|
||||
private WxMaService createWxMaService(String appId, String appSecret, String accessToken) {
|
||||
private WxMaService createWxMaService(String wxAppId, String appSecret, String accessToken) {
|
||||
WxMaService wxMaService = new WxMaServiceImpl();
|
||||
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
|
||||
config.setAppid(appId);
|
||||
config.setAppid(wxAppId);
|
||||
config.setSecret(appSecret);
|
||||
config.setToken(accessToken);
|
||||
wxMaService.setWxMaConfig(config);
|
||||
|
||||
@@ -171,7 +171,7 @@ public class WechatMessageRecordService {
|
||||
@SuppressWarnings("unchecked")
|
||||
private TemplateMessageParam buildTemplateMessageParam(WechatMessageRecord record) {
|
||||
TemplateMessageParam param = new TemplateMessageParam();
|
||||
param.setAppId(record.getAppId());
|
||||
param.setWxAppId(record.getWxAppId());
|
||||
// AppSecret需要从外部传入,这里暂时为空,实际使用时需要调用方提供
|
||||
param.setOpenId(record.getOpenId());
|
||||
param.setTemplateId(record.getTemplateId());
|
||||
@@ -186,12 +186,12 @@ public class WechatMessageRecordService {
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
|
||||
/// 构建统一服务消息参数
|
||||
@SuppressWarnings("unchecked")
|
||||
private UniformMessageParam buildUniformMessageParam(WechatMessageRecord record) {
|
||||
UniformMessageParam param = new UniformMessageParam();
|
||||
param.setAppId(record.getAppId());
|
||||
param.setWxAppId(record.getWxAppId());
|
||||
// AppSecret需要从外部传入,这里暂时为空,实际使用时需要调用方提供
|
||||
param.setOpenId(record.getOpenId());
|
||||
param.setTemplateId(record.getTemplateId());
|
||||
|
||||
@@ -41,7 +41,7 @@ public class WechatMpMessageService {
|
||||
/// @return 消息发送结果
|
||||
public MessageSendResult sendTemplateMessage(TemplateMessageParam param) {
|
||||
// 验证配置参数
|
||||
validateConfig(param.getAppId(), param.getAppSecret());
|
||||
validateConfig(param.getWxAppId(), param.getAppSecret());
|
||||
|
||||
// 创建消息记录
|
||||
WechatMessageRecord record = createMessageRecord(param);
|
||||
@@ -53,13 +53,13 @@ public class WechatMpMessageService {
|
||||
|
||||
try {
|
||||
// 获取AccessToken
|
||||
String accessToken = tokenService.getAccessToken(param.getAppId(), param.getAppSecret());
|
||||
String accessToken = tokenService.getAccessToken(param.getWxAppId(), param.getAppSecret());
|
||||
|
||||
// 构建模板消息
|
||||
WxMpTemplateMessage templateMessage = buildTemplateMessage(param);
|
||||
|
||||
// 创建微信服务
|
||||
WxMpService wxMpService = createWxMpService(param.getAppId(), param.getAppSecret(), accessToken);
|
||||
WxMpService wxMpService = createWxMpService(param.getWxAppId(), param.getAppSecret(), accessToken);
|
||||
|
||||
// 发送消息
|
||||
String msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
|
||||
@@ -146,9 +146,9 @@ public class WechatMpMessageService {
|
||||
}
|
||||
|
||||
/// 验证配置参数
|
||||
private void validateConfig(String appId, String appSecret) {
|
||||
if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) {
|
||||
log.error("微信配置参数为空,appId: {}", appId);
|
||||
private void validateConfig(String wxAppId, String appSecret) {
|
||||
if (StrUtil.isBlank(wxAppId) || StrUtil.isBlank(appSecret)) {
|
||||
log.error("微信配置参数为空,wxAppId: {}", wxAppId);
|
||||
// 微信配置参数不能为空
|
||||
throw new OperationFailException("error.channel.wechat.configParamsRequired");
|
||||
}
|
||||
@@ -165,7 +165,7 @@ public class WechatMpMessageService {
|
||||
record.setStatus("sending");
|
||||
record.setSendTime(OffsetDateTime.now(ZoneOffset.UTC));
|
||||
record.setScene(param.getScene());
|
||||
record.setAppId(param.getAppId());
|
||||
record.setWxAppId(param.getWxAppId());
|
||||
return record;
|
||||
}
|
||||
|
||||
@@ -190,10 +190,10 @@ public class WechatMpMessageService {
|
||||
}
|
||||
|
||||
/// 创建微信公众号Service
|
||||
private WxMpService createWxMpService(String appId, String appSecret, String accessToken) {
|
||||
private WxMpService createWxMpService(String wxAppId, String appSecret, String accessToken) {
|
||||
WxMpService wxMpService = new WxMpServiceImpl();
|
||||
WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
|
||||
config.setAppId(appId);
|
||||
config.setAppId(wxAppId);
|
||||
config.setSecret(appSecret);
|
||||
config.setAccessToken(accessToken);
|
||||
wxMpService.setWxMpConfigStorage(config);
|
||||
|
||||
@@ -34,38 +34,38 @@ public class WechatTokenService {
|
||||
private static final long TOKEN_EXPIRE_TIME = 7200 - 300;
|
||||
|
||||
/// 获取AccessToken(自动刷新,支持多副本部署)
|
||||
/// @param appId AppId
|
||||
/// @param wxAppId 微信AppId
|
||||
/// @param appSecret AppSecret
|
||||
/// @return AccessToken
|
||||
public String getAccessToken(String appId, String appSecret) {
|
||||
String cacheKey = TOKEN_CACHE_KEY + appId;
|
||||
public String getAccessToken(String wxAppId, String appSecret) {
|
||||
String cacheKey = TOKEN_CACHE_KEY + wxAppId;
|
||||
|
||||
// 从缓存获取Token
|
||||
String token = redisTemplate.opsForValue().get(cacheKey);
|
||||
|
||||
// 如果Token存在且未即将过期,直接返回
|
||||
if (StrUtil.isNotBlank(token) && !isTokenExpiringSoon(appId)) {
|
||||
log.debug("从缓存获取AccessToken成功,appId: {}", appId);
|
||||
if (StrUtil.isNotBlank(token) && !isTokenExpiringSoon(wxAppId)) {
|
||||
log.debug("从缓存获取AccessToken成功,wxAppId: {}", wxAppId);
|
||||
return token;
|
||||
}
|
||||
|
||||
// Token不存在或即将过期,需要刷新
|
||||
return refreshAccessToken(appId, appSecret);
|
||||
return refreshAccessToken(wxAppId, appSecret);
|
||||
}
|
||||
|
||||
/// 手动刷新AccessToken(使用lock4j分布式锁)
|
||||
/// @param appId AppId
|
||||
/// @param appSecret AppSecret
|
||||
/// @return 新的AccessToken
|
||||
public String refreshAccessToken(String appId, String appSecret) {
|
||||
String lockKey = TOKEN_LOCK_KEY + appId;
|
||||
String cacheKey = TOKEN_CACHE_KEY + appId;
|
||||
String expireKey = TOKEN_EXPIRE_KEY + appId;
|
||||
public String refreshAccessToken(String wxAppId, String appSecret) {
|
||||
String lockKey = TOKEN_LOCK_KEY + wxAppId;
|
||||
String cacheKey = TOKEN_CACHE_KEY + wxAppId;
|
||||
String expireKey = TOKEN_EXPIRE_KEY + wxAppId;
|
||||
|
||||
// 使用lock4j获取分布式锁
|
||||
LockInfo lockInfo = lockTemplate.lock(lockKey, 30000L, 5000L);
|
||||
if (lockInfo == null) {
|
||||
log.warn("获取Token刷新锁失败,appId: {}", appId);
|
||||
log.warn("获取Token刷新锁失败,wxAppId: {}", wxAppId);
|
||||
// 获取锁失败,尝试从缓存获取
|
||||
String token = redisTemplate.opsForValue().get(cacheKey);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
@@ -77,19 +77,19 @@ public class WechatTokenService {
|
||||
try {
|
||||
// 双重检查,避免重复刷新
|
||||
String token = redisTemplate.opsForValue().get(cacheKey);
|
||||
if (StrUtil.isNotBlank(token) && !isTokenExpiringSoon(appId)) {
|
||||
log.debug("其他实例已刷新Token,直接返回,appId: {}", appId);
|
||||
if (StrUtil.isNotBlank(token) && !isTokenExpiringSoon(wxAppId)) {
|
||||
log.debug("其他实例已刷新Token,直接返回,wxAppId: {}", wxAppId);
|
||||
return token;
|
||||
}
|
||||
|
||||
// 调用微信API获取新Token
|
||||
log.info("开始刷新AccessToken,appId: {}", appId);
|
||||
WxMpService wxMpService = createWxMpService(appId, appSecret);
|
||||
log.info("开始刷新AccessToken,wxAppId: {}", wxAppId);
|
||||
WxMpService wxMpService = createWxMpService(wxAppId, appSecret);
|
||||
String newToken;
|
||||
try {
|
||||
newToken = wxMpService.getAccessToken();
|
||||
} catch (WxErrorException e) {
|
||||
log.error("调用微信API获取AccessToken失败,appId: {}, 错误: {}", appId, e.getMessage());
|
||||
log.error("调用微信API获取AccessToken失败,wxAppId: {}, 错误: {}", wxAppId, e.getMessage());
|
||||
throw new RuntimeException("刷新AccessToken失败: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public class WechatTokenService {
|
||||
long expireTime = System.currentTimeMillis() + TOKEN_EXPIRE_TIME * 1000;
|
||||
redisTemplate.opsForValue().set(expireKey, String.valueOf(expireTime), TOKEN_EXPIRE_TIME, TimeUnit.SECONDS);
|
||||
|
||||
log.info("刷新AccessToken成功,appId: {}", appId);
|
||||
log.info("刷新AccessToken成功,wxAppId: {}", wxAppId);
|
||||
return newToken;
|
||||
|
||||
} finally {
|
||||
@@ -113,10 +113,10 @@ public class WechatTokenService {
|
||||
}
|
||||
|
||||
/// 检查Token是否即将过期(过期前5分钟)
|
||||
/// @param appId AppId
|
||||
/// @param wxAppId 微信AppId
|
||||
/// @return 是否即将过期
|
||||
public boolean isTokenExpiringSoon(String appId) {
|
||||
String expireKey = TOKEN_EXPIRE_KEY + appId;
|
||||
public boolean isTokenExpiringSoon(String wxAppId) {
|
||||
String expireKey = TOKEN_EXPIRE_KEY + wxAppId;
|
||||
String expireTimeStr = redisTemplate.opsForValue().get(expireKey);
|
||||
|
||||
if (StrUtil.isBlank(expireTimeStr)) {
|
||||
@@ -129,16 +129,16 @@ public class WechatTokenService {
|
||||
// 提前5分钟判断为即将过期
|
||||
return (expireTime - currentTime) < 300000;
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("解析Token过期时间失败,appId: {}", appId);
|
||||
log.warn("解析Token过期时间失败,wxAppId: {}", wxAppId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// 创建微信公众号Service
|
||||
private WxMpService createWxMpService(String appId, String appSecret) {
|
||||
private WxMpService createWxMpService(String wxAppId, String appSecret) {
|
||||
WxMpService wxMpService = new WxMpServiceImpl();
|
||||
WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
|
||||
config.setAppId(appId);
|
||||
config.setAppId(wxAppId);
|
||||
config.setSecret(appSecret);
|
||||
wxMpService.setWxMpConfigStorage(config);
|
||||
return wxMpService;
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
-- 微信消息记录表
|
||||
CREATE TABLE IF NOT EXISTS pay_platform_wechat_message_record (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
message_type VARCHAR(20) NOT NULL,
|
||||
open_id VARCHAR(64) NOT NULL,
|
||||
template_id VARCHAR(64) NOT NULL,
|
||||
template_data TEXT,
|
||||
url VARCHAR(500),
|
||||
status VARCHAR(20) NOT NULL,
|
||||
msg_id VARCHAR(64),
|
||||
error_code VARCHAR(20),
|
||||
error_msg VARCHAR(500),
|
||||
send_time TIMESTAMP,
|
||||
scene VARCHAR(50),
|
||||
app_id VARCHAR(32),
|
||||
creator BIGINT,
|
||||
create_time TIMESTAMP,
|
||||
updater BIGINT,
|
||||
update_time TIMESTAMP,
|
||||
deleted SMALLINT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 添加注释
|
||||
COMMENT ON TABLE pay_platform_wechat_message_record IS '微信消息记录表';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.id IS '主键ID';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.message_type IS '消息类型:template-公众号模板消息,uniform-小程序统一服务消息';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.open_id IS '接收者OpenId';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.template_id IS '模板ID';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.template_data IS '模板数据(JSON格式)';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.url IS '跳转链接或小程序页面路径';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.status IS '发送状态:success-成功,failed-失败,retry-待重试';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.msg_id IS '微信消息ID';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.error_code IS '错误码';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.error_msg IS '错误信息';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.send_time IS '发送时间';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.scene IS '业务场景标识';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.app_id IS '使用的AppId';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.creator IS '创建者';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.updater IS '更新者';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN pay_platform_wechat_message_record.deleted IS '删除标志';
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_wechat_msg_open_id ON pay_platform_wechat_message_record(open_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_wechat_msg_status ON pay_platform_wechat_message_record(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_wechat_msg_scene ON pay_platform_wechat_message_record(scene);
|
||||
CREATE INDEX IF NOT EXISTS idx_wechat_msg_send_time ON pay_platform_wechat_message_record(send_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_wechat_msg_app_id ON pay_platform_wechat_message_record(app_id);
|
||||
@@ -81,6 +81,12 @@
|
||||
"notNull": "Primary key cannot be blank",
|
||||
"mustBeNullOnAdd": "Id must be empty"
|
||||
},
|
||||
"alipayIsvAppId": {
|
||||
"notNull": "Alipay ISV app id cannot be null"
|
||||
},
|
||||
"alipayDirectAppId": {
|
||||
"notNull": "Alipay direct app id cannot be null"
|
||||
},
|
||||
"account": {
|
||||
"notBlank": "Account cannot be blank",
|
||||
"size": "Account length must be between 6 and 20 characters",
|
||||
|
||||
@@ -81,6 +81,12 @@
|
||||
"notNull": "主键不可为空",
|
||||
"mustBeNullOnAdd": "Id需要为空"
|
||||
},
|
||||
"alipayIsvAppId": {
|
||||
"notNull": "支付宝服务商应用ID不可为空"
|
||||
},
|
||||
"alipayDirectAppId": {
|
||||
"notNull": "支付宝直连应用ID不可为空"
|
||||
},
|
||||
"account": {
|
||||
"notBlank": "登录账号不可为空",
|
||||
"size": "账号长度为6-20个字符",
|
||||
|
||||
Reference in New Issue
Block a user