mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
feat: add payment gateway and billing plans
This commit is contained in:
@@ -458,6 +458,13 @@ CREATE TABLE IF NOT EXISTS public.payment_orders (
|
||||
refunded_amount_usd numeric(20,8) DEFAULT '0'::numeric NOT NULL,
|
||||
refundable_amount_usd numeric(20,8) DEFAULT '0'::numeric NOT NULL,
|
||||
payment_method character varying(30) NOT NULL,
|
||||
payment_provider character varying(64),
|
||||
payment_channel character varying(64),
|
||||
order_kind character varying(64) DEFAULT 'wallet_recharge'::character varying NOT NULL,
|
||||
product_id character varying(64),
|
||||
product_snapshot jsonb,
|
||||
fulfillment_status character varying(64) DEFAULT 'pending'::character varying NOT NULL,
|
||||
fulfillment_error text,
|
||||
gateway_order_id character varying(128),
|
||||
gateway_response jsonb,
|
||||
status character varying(20) DEFAULT 'pending'::character varying NOT NULL,
|
||||
@@ -469,6 +476,87 @@ CREATE TABLE IF NOT EXISTS public.payment_orders (
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: payment_gateway_configs; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.payment_gateway_configs (
|
||||
provider character varying(64) NOT NULL,
|
||||
enabled boolean DEFAULT false NOT NULL,
|
||||
endpoint_url character varying(512) NOT NULL,
|
||||
callback_base_url character varying(512),
|
||||
merchant_id character varying(128) NOT NULL,
|
||||
merchant_key_encrypted text,
|
||||
pay_currency character varying(16) DEFAULT 'CNY'::character varying NOT NULL,
|
||||
usd_exchange_rate numeric(18,8) DEFAULT 7.2 NOT NULL,
|
||||
min_recharge_usd numeric(20,8) DEFAULT 1 NOT NULL,
|
||||
channels_json jsonb,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: billing_plans; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.billing_plans (
|
||||
id character varying(64) NOT NULL,
|
||||
title character varying(128) NOT NULL,
|
||||
description text,
|
||||
price_amount numeric(20,8) NOT NULL,
|
||||
price_currency character varying(16) DEFAULT 'CNY'::character varying NOT NULL,
|
||||
duration_unit character varying(32) NOT NULL,
|
||||
duration_value bigint NOT NULL,
|
||||
enabled boolean DEFAULT true NOT NULL,
|
||||
sort_order bigint DEFAULT 0 NOT NULL,
|
||||
max_active_per_user bigint DEFAULT 1 NOT NULL,
|
||||
purchase_limit_scope character varying(32) DEFAULT 'active_period'::character varying NOT NULL,
|
||||
entitlements_json jsonb NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: user_plan_entitlements; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.user_plan_entitlements (
|
||||
id character varying(64) NOT NULL,
|
||||
user_id character varying(64) NOT NULL,
|
||||
plan_id character varying(64) NOT NULL,
|
||||
payment_order_id character varying(64) NOT NULL,
|
||||
status character varying(64) DEFAULT 'active'::character varying NOT NULL,
|
||||
starts_at timestamp with time zone NOT NULL,
|
||||
expires_at timestamp with time zone NOT NULL,
|
||||
entitlements_snapshot jsonb NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: entitlement_usage_ledgers; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.entitlement_usage_ledgers (
|
||||
id character varying(64) NOT NULL,
|
||||
user_entitlement_id character varying(64) NOT NULL,
|
||||
user_id character varying(64) NOT NULL,
|
||||
request_id character varying(128) NOT NULL,
|
||||
amount_usd numeric(20,8) NOT NULL,
|
||||
balance_before numeric(20,8) NOT NULL,
|
||||
balance_after numeric(20,8) NOT NULL,
|
||||
usage_date character varying(16) NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: provider_api_keys; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -87,6 +87,21 @@ END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: billing_plans billing_plans_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.billing_plans
|
||||
ADD CONSTRAINT billing_plans_pkey PRIMARY KEY (id);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: dimension_collectors dimension_collectors_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -222,6 +237,21 @@ END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: payment_gateway_configs payment_gateway_configs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.payment_gateway_configs
|
||||
ADD CONSTRAINT payment_gateway_configs_pkey PRIMARY KEY (provider);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: payment_orders payment_orders_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -237,6 +267,21 @@ END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: entitlement_usage_ledgers entitlement_usage_ledgers_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.entitlement_usage_ledgers
|
||||
ADD CONSTRAINT entitlement_usage_ledgers_pkey PRIMARY KEY (id);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: provider_api_keys provider_api_keys_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -597,6 +642,21 @@ END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: entitlement_usage_ledgers uq_entitlement_usage_request; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.entitlement_usage_ledgers
|
||||
ADD CONSTRAINT uq_entitlement_usage_request UNIQUE (user_entitlement_id, request_id);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: payment_callbacks uq_payment_callbacks_callback_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1152,6 +1212,21 @@ END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: user_plan_entitlements user_plan_entitlements_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.user_plan_entitlements
|
||||
ADD CONSTRAINT user_plan_entitlements_pkey PRIMARY KEY (id);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: video_tasks video_tasks_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -101,6 +101,22 @@ CREATE INDEX IF NOT EXISTS idx_payment_orders_gateway_order_id ON public.payment
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_payment_orders_kind_status; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_kind_status ON public.payment_orders USING btree (order_kind, status);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_payment_orders_product; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_product ON public.payment_orders USING btree (product_id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_payment_orders_status; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -125,6 +141,38 @@ CREATE INDEX IF NOT EXISTS idx_payment_orders_wallet_created ON public.payment_o
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_billing_plans_enabled_sort; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_billing_plans_enabled_sort ON public.billing_plans USING btree (enabled, sort_order);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_user_plan_entitlements_user_active; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_user_active ON public.user_plan_entitlements USING btree (user_id, status, expires_at);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_user_plan_entitlements_order; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_order ON public.user_plan_entitlements USING btree (payment_order_id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_entitlement_usage_user_date; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_entitlement_usage_user_date ON public.entitlement_usage_ledgers USING btree (user_id, usage_date);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_active; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -267,6 +267,81 @@ END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: user_plan_entitlements user_plan_entitlements_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.user_plan_entitlements
|
||||
ADD CONSTRAINT user_plan_entitlements_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: user_plan_entitlements user_plan_entitlements_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.user_plan_entitlements
|
||||
ADD CONSTRAINT user_plan_entitlements_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.billing_plans(id) ON DELETE RESTRICT;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: user_plan_entitlements user_plan_entitlements_payment_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.user_plan_entitlements
|
||||
ADD CONSTRAINT user_plan_entitlements_payment_order_id_fkey FOREIGN KEY (payment_order_id) REFERENCES public.payment_orders(id) ON DELETE RESTRICT;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: entitlement_usage_ledgers entitlement_usage_ledgers_user_entitlement_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.entitlement_usage_ledgers
|
||||
ADD CONSTRAINT entitlement_usage_ledgers_user_entitlement_id_fkey FOREIGN KEY (user_entitlement_id) REFERENCES public.user_plan_entitlements(id) ON DELETE CASCADE;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: entitlement_usage_ledgers entitlement_usage_ledgers_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
DO $mig$ BEGIN
|
||||
ALTER TABLE ONLY public.entitlement_usage_ledgers
|
||||
ADD CONSTRAINT entitlement_usage_ledgers_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN NULL;
|
||||
WHEN duplicate_table THEN NULL;
|
||||
WHEN invalid_table_definition THEN NULL;
|
||||
END $mig$;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: provider_endpoints provider_endpoints_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -80,6 +80,13 @@ CREATE TABLE IF NOT EXISTS payment_orders (
|
||||
`refunded_amount_usd` DOUBLE NOT NULL DEFAULT 0,
|
||||
`refundable_amount_usd` DOUBLE NOT NULL DEFAULT 0,
|
||||
`payment_method` VARCHAR(64) NOT NULL,
|
||||
`payment_provider` VARCHAR(64),
|
||||
`payment_channel` VARCHAR(64),
|
||||
`order_kind` VARCHAR(64) NOT NULL DEFAULT 'wallet_recharge',
|
||||
`product_id` VARCHAR(64),
|
||||
`product_snapshot` JSON,
|
||||
`fulfillment_status` VARCHAR(64) NOT NULL DEFAULT 'pending',
|
||||
`fulfillment_error` LONGTEXT,
|
||||
`gateway_order_id` VARCHAR(128),
|
||||
`gateway_response` JSON,
|
||||
`status` VARCHAR(64) NOT NULL DEFAULT 'pending',
|
||||
@@ -92,7 +99,25 @@ CREATE TABLE IF NOT EXISTS payment_orders (
|
||||
KEY idx_payment_orders_wallet_created (`wallet_id`, `created_at`),
|
||||
KEY idx_payment_orders_user_created (`user_id`, `created_at`),
|
||||
KEY idx_payment_orders_status (`status`),
|
||||
KEY idx_payment_orders_gateway_order_id (`gateway_order_id`)
|
||||
KEY idx_payment_orders_gateway_order_id (`gateway_order_id`),
|
||||
KEY idx_payment_orders_kind_status (`order_kind`, `status`),
|
||||
KEY idx_payment_orders_product (`product_id`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_gateway_configs (
|
||||
`provider` VARCHAR(64) NOT NULL,
|
||||
`enabled` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`endpoint_url` VARCHAR(512) NOT NULL,
|
||||
`callback_base_url` VARCHAR(512),
|
||||
`merchant_id` VARCHAR(128) NOT NULL,
|
||||
`merchant_key_encrypted` LONGTEXT,
|
||||
`pay_currency` VARCHAR(16) NOT NULL DEFAULT 'CNY',
|
||||
`usd_exchange_rate` DOUBLE NOT NULL DEFAULT 7.2,
|
||||
`min_recharge_usd` DOUBLE NOT NULL DEFAULT 1,
|
||||
`channels_json` JSON,
|
||||
`created_at` BIGINT NOT NULL,
|
||||
`updated_at` BIGINT NOT NULL,
|
||||
PRIMARY KEY (`provider`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_callbacks (
|
||||
@@ -117,6 +142,56 @@ CREATE TABLE IF NOT EXISTS payment_callbacks (
|
||||
KEY ix_payment_callbacks_payment_order_id (`payment_order_id`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS billing_plans (
|
||||
`id` VARCHAR(64) NOT NULL,
|
||||
`title` VARCHAR(128) NOT NULL,
|
||||
`description` LONGTEXT,
|
||||
`price_amount` DOUBLE NOT NULL,
|
||||
`price_currency` VARCHAR(16) NOT NULL DEFAULT 'CNY',
|
||||
`duration_unit` VARCHAR(32) NOT NULL,
|
||||
`duration_value` BIGINT NOT NULL,
|
||||
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`sort_order` BIGINT NOT NULL DEFAULT 0,
|
||||
`max_active_per_user` BIGINT NOT NULL DEFAULT 1,
|
||||
`purchase_limit_scope` VARCHAR(32) NOT NULL DEFAULT 'active_period',
|
||||
`entitlements_json` JSON NOT NULL,
|
||||
`created_at` BIGINT NOT NULL,
|
||||
`updated_at` BIGINT NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY idx_billing_plans_enabled_sort (`enabled`, `sort_order`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_plan_entitlements (
|
||||
`id` VARCHAR(64) NOT NULL,
|
||||
`user_id` VARCHAR(64) NOT NULL,
|
||||
`plan_id` VARCHAR(64) NOT NULL,
|
||||
`payment_order_id` VARCHAR(64) NOT NULL,
|
||||
`status` VARCHAR(64) NOT NULL DEFAULT 'active',
|
||||
`starts_at` BIGINT NOT NULL,
|
||||
`expires_at` BIGINT NOT NULL,
|
||||
`entitlements_snapshot` JSON NOT NULL,
|
||||
`created_at` BIGINT NOT NULL,
|
||||
`updated_at` BIGINT NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY idx_user_plan_entitlements_user_active (`user_id`, `status`, `expires_at`),
|
||||
KEY idx_user_plan_entitlements_order (`payment_order_id`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS entitlement_usage_ledgers (
|
||||
`id` VARCHAR(64) NOT NULL,
|
||||
`user_entitlement_id` VARCHAR(64) NOT NULL,
|
||||
`user_id` VARCHAR(64) NOT NULL,
|
||||
`request_id` VARCHAR(128) NOT NULL,
|
||||
`amount_usd` DOUBLE NOT NULL,
|
||||
`balance_before` DOUBLE NOT NULL,
|
||||
`balance_after` DOUBLE NOT NULL,
|
||||
`usage_date` VARCHAR(16) NOT NULL,
|
||||
`created_at` BIGINT NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY uq_entitlement_usage_request (`user_entitlement_id`, `request_id`),
|
||||
KEY idx_entitlement_usage_user_date (`user_id`, `usage_date`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS refund_requests (
|
||||
`id` VARCHAR(64) NOT NULL,
|
||||
`refund_no` VARCHAR(128) NOT NULL,
|
||||
|
||||
@@ -83,6 +83,13 @@ CREATE TABLE IF NOT EXISTS public.payment_orders (
|
||||
refunded_amount_usd double precision DEFAULT 0 NOT NULL,
|
||||
refundable_amount_usd double precision DEFAULT 0 NOT NULL,
|
||||
payment_method character varying(64) NOT NULL,
|
||||
payment_provider character varying(64),
|
||||
payment_channel character varying(64),
|
||||
order_kind character varying(64) DEFAULT 'wallet_recharge' NOT NULL,
|
||||
product_id character varying(64),
|
||||
product_snapshot jsonb,
|
||||
fulfillment_status character varying(64) DEFAULT 'pending' NOT NULL,
|
||||
fulfillment_error text,
|
||||
gateway_order_id character varying(128),
|
||||
gateway_response jsonb,
|
||||
status character varying(64) DEFAULT 'pending' NOT NULL,
|
||||
@@ -98,6 +105,25 @@ CREATE INDEX IF NOT EXISTS idx_payment_orders_wallet_created ON public.payment_o
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_user_created ON public.payment_orders USING btree (user_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_status ON public.payment_orders USING btree (status);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_gateway_order_id ON public.payment_orders USING btree (gateway_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_kind_status ON public.payment_orders USING btree (order_kind, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_product ON public.payment_orders USING btree (product_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.payment_gateway_configs (
|
||||
provider character varying(64) NOT NULL,
|
||||
enabled boolean DEFAULT false NOT NULL,
|
||||
endpoint_url character varying(512) NOT NULL,
|
||||
callback_base_url character varying(512),
|
||||
merchant_id character varying(128) NOT NULL,
|
||||
merchant_key_encrypted text,
|
||||
pay_currency character varying(16) DEFAULT 'CNY' NOT NULL,
|
||||
usd_exchange_rate double precision DEFAULT 7.2 NOT NULL,
|
||||
min_recharge_usd double precision DEFAULT 1 NOT NULL,
|
||||
channels_json jsonb,
|
||||
created_at bigint NOT NULL,
|
||||
updated_at bigint NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY public.payment_gateway_configs ADD CONSTRAINT payment_gateway_configs_pkey PRIMARY KEY (provider);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.payment_callbacks (
|
||||
id character varying(64) NOT NULL,
|
||||
@@ -122,6 +148,59 @@ CREATE INDEX IF NOT EXISTS idx_payment_callbacks_gateway_order ON public.payment
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_callbacks_created ON public.payment_callbacks USING btree (created_at);
|
||||
CREATE INDEX IF NOT EXISTS ix_payment_callbacks_payment_order_id ON public.payment_callbacks USING btree (payment_order_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.billing_plans (
|
||||
id character varying(64) NOT NULL,
|
||||
title character varying(128) NOT NULL,
|
||||
description text,
|
||||
price_amount double precision NOT NULL,
|
||||
price_currency character varying(16) DEFAULT 'CNY' NOT NULL,
|
||||
duration_unit character varying(32) NOT NULL,
|
||||
duration_value bigint NOT NULL,
|
||||
enabled boolean DEFAULT true NOT NULL,
|
||||
sort_order bigint DEFAULT 0 NOT NULL,
|
||||
max_active_per_user bigint DEFAULT 1 NOT NULL,
|
||||
purchase_limit_scope character varying(32) DEFAULT 'active_period' NOT NULL,
|
||||
entitlements_json jsonb NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
updated_at bigint NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY public.billing_plans ADD CONSTRAINT billing_plans_pkey PRIMARY KEY (id);
|
||||
CREATE INDEX IF NOT EXISTS idx_billing_plans_enabled_sort ON public.billing_plans USING btree (enabled, sort_order);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.user_plan_entitlements (
|
||||
id character varying(64) NOT NULL,
|
||||
user_id character varying(64) NOT NULL,
|
||||
plan_id character varying(64) NOT NULL,
|
||||
payment_order_id character varying(64) NOT NULL,
|
||||
status character varying(64) DEFAULT 'active' NOT NULL,
|
||||
starts_at bigint NOT NULL,
|
||||
expires_at bigint NOT NULL,
|
||||
entitlements_snapshot jsonb NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
updated_at bigint NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY public.user_plan_entitlements ADD CONSTRAINT user_plan_entitlements_pkey PRIMARY KEY (id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_user_active ON public.user_plan_entitlements USING btree (user_id, status, expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_order ON public.user_plan_entitlements USING btree (payment_order_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.entitlement_usage_ledgers (
|
||||
id character varying(64) NOT NULL,
|
||||
user_entitlement_id character varying(64) NOT NULL,
|
||||
user_id character varying(64) NOT NULL,
|
||||
request_id character varying(128) NOT NULL,
|
||||
amount_usd double precision NOT NULL,
|
||||
balance_before double precision NOT NULL,
|
||||
balance_after double precision NOT NULL,
|
||||
usage_date character varying(16) NOT NULL,
|
||||
created_at bigint NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY public.entitlement_usage_ledgers ADD CONSTRAINT entitlement_usage_ledgers_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE ONLY public.entitlement_usage_ledgers ADD CONSTRAINT uq_entitlement_usage_request UNIQUE (user_entitlement_id, request_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_entitlement_usage_user_date ON public.entitlement_usage_ledgers USING btree (user_id, usage_date);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.refund_requests (
|
||||
id character varying(64) NOT NULL,
|
||||
refund_no character varying(128) NOT NULL,
|
||||
|
||||
@@ -77,6 +77,13 @@ CREATE TABLE IF NOT EXISTS payment_orders (
|
||||
refunded_amount_usd REAL NOT NULL DEFAULT 0,
|
||||
refundable_amount_usd REAL NOT NULL DEFAULT 0,
|
||||
payment_method TEXT NOT NULL,
|
||||
payment_provider TEXT,
|
||||
payment_channel TEXT,
|
||||
order_kind TEXT NOT NULL DEFAULT 'wallet_recharge',
|
||||
product_id TEXT,
|
||||
product_snapshot TEXT,
|
||||
fulfillment_status TEXT NOT NULL DEFAULT 'pending',
|
||||
fulfillment_error TEXT,
|
||||
gateway_order_id TEXT,
|
||||
gateway_response TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
@@ -90,6 +97,23 @@ CREATE INDEX IF NOT EXISTS idx_payment_orders_wallet_created ON payment_orders (
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_user_created ON payment_orders (user_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_status ON payment_orders (status);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_gateway_order_id ON payment_orders (gateway_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_kind_status ON payment_orders (order_kind, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_orders_product ON payment_orders (product_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_gateway_configs (
|
||||
provider TEXT PRIMARY KEY NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 0,
|
||||
endpoint_url TEXT NOT NULL,
|
||||
callback_base_url TEXT,
|
||||
merchant_id TEXT NOT NULL,
|
||||
merchant_key_encrypted TEXT,
|
||||
pay_currency TEXT NOT NULL DEFAULT 'CNY',
|
||||
usd_exchange_rate REAL NOT NULL DEFAULT 7.2,
|
||||
min_recharge_usd REAL NOT NULL DEFAULT 1,
|
||||
channels_json TEXT,
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_callbacks (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
@@ -112,6 +136,53 @@ CREATE INDEX IF NOT EXISTS idx_payment_callbacks_gateway_order ON payment_callba
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_callbacks_created ON payment_callbacks (created_at);
|
||||
CREATE INDEX IF NOT EXISTS ix_payment_callbacks_payment_order_id ON payment_callbacks (payment_order_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS billing_plans (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
price_amount REAL NOT NULL,
|
||||
price_currency TEXT NOT NULL DEFAULT 'CNY',
|
||||
duration_unit TEXT NOT NULL,
|
||||
duration_value INTEGER NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
max_active_per_user INTEGER NOT NULL DEFAULT 1,
|
||||
purchase_limit_scope TEXT NOT NULL DEFAULT 'active_period',
|
||||
entitlements_json TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_billing_plans_enabled_sort ON billing_plans (enabled, sort_order);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_plan_entitlements (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
plan_id TEXT NOT NULL,
|
||||
payment_order_id TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
starts_at INTEGER NOT NULL,
|
||||
expires_at INTEGER NOT NULL,
|
||||
entitlements_snapshot TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_user_active ON user_plan_entitlements (user_id, status, expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_order ON user_plan_entitlements (payment_order_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS entitlement_usage_ledgers (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
user_entitlement_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
request_id TEXT NOT NULL,
|
||||
amount_usd REAL NOT NULL,
|
||||
balance_before REAL NOT NULL,
|
||||
balance_after REAL NOT NULL,
|
||||
usage_date TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
UNIQUE (user_entitlement_id, request_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_entitlement_usage_user_date ON entitlement_usage_ledgers (user_id, usage_date);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS refund_requests (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
refund_no TEXT NOT NULL,
|
||||
|
||||
@@ -334,6 +334,46 @@ name = "payment_method"
|
||||
type = "text"
|
||||
length = 64
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "payment_provider"
|
||||
type = "text"
|
||||
length = 64
|
||||
nullable = true
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "payment_channel"
|
||||
type = "text"
|
||||
length = 64
|
||||
nullable = true
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "order_kind"
|
||||
type = "text"
|
||||
length = 64
|
||||
default = "wallet_recharge"
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "product_id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
nullable = true
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "product_snapshot"
|
||||
type = "json"
|
||||
nullable = true
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "fulfillment_status"
|
||||
type = "text"
|
||||
length = 64
|
||||
default = "pending"
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "fulfillment_error"
|
||||
type = "long_text"
|
||||
nullable = true
|
||||
|
||||
[[table.payment_orders.columns]]
|
||||
name = "gateway_order_id"
|
||||
type = "text"
|
||||
@@ -390,6 +430,79 @@ columns = ["status"]
|
||||
name = "idx_payment_orders_gateway_order_id"
|
||||
columns = ["gateway_order_id"]
|
||||
|
||||
[[table.payment_orders.indexes]]
|
||||
name = "idx_payment_orders_kind_status"
|
||||
columns = ["order_kind", "status"]
|
||||
|
||||
[[table.payment_orders.indexes]]
|
||||
name = "idx_payment_orders_product"
|
||||
columns = ["product_id"]
|
||||
|
||||
[table.payment_gateway_configs]
|
||||
domain = "wallet_billing"
|
||||
order = 45
|
||||
primary_key = ["provider"]
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "provider"
|
||||
type = "text"
|
||||
length = 64
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "enabled"
|
||||
type = "bool"
|
||||
default = false
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "endpoint_url"
|
||||
type = "text"
|
||||
length = 512
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "callback_base_url"
|
||||
type = "text"
|
||||
length = 512
|
||||
nullable = true
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "merchant_id"
|
||||
type = "text"
|
||||
length = 128
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "merchant_key_encrypted"
|
||||
type = "long_text"
|
||||
nullable = true
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "pay_currency"
|
||||
type = "text"
|
||||
length = 16
|
||||
default = "CNY"
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "usd_exchange_rate"
|
||||
type = "float64"
|
||||
default = { raw = "7.2" }
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "min_recharge_usd"
|
||||
type = "float64"
|
||||
default = 1
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "channels_json"
|
||||
type = "json"
|
||||
nullable = true
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "created_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.payment_gateway_configs.columns]]
|
||||
name = "updated_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[table.payment_callbacks]
|
||||
domain = "wallet_billing"
|
||||
order = 50
|
||||
@@ -468,6 +581,195 @@ nullable = true
|
||||
name = "uq_payment_callbacks_callback_key"
|
||||
columns = ["callback_key"]
|
||||
|
||||
[table.billing_plans]
|
||||
domain = "wallet_billing"
|
||||
order = 55
|
||||
primary_key = ["id"]
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "title"
|
||||
type = "text"
|
||||
length = 128
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "description"
|
||||
type = "long_text"
|
||||
nullable = true
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "price_amount"
|
||||
type = "float64"
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "price_currency"
|
||||
type = "text"
|
||||
length = 16
|
||||
default = "CNY"
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "duration_unit"
|
||||
type = "text"
|
||||
length = 32
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "duration_value"
|
||||
type = "int64"
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "enabled"
|
||||
type = "bool"
|
||||
default = true
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "sort_order"
|
||||
type = "int64"
|
||||
default = 0
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "max_active_per_user"
|
||||
type = "int64"
|
||||
default = 1
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "purchase_limit_scope"
|
||||
type = "text"
|
||||
length = 32
|
||||
default = "active_period"
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "entitlements_json"
|
||||
type = "json"
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "created_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.billing_plans.columns]]
|
||||
name = "updated_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.billing_plans.indexes]]
|
||||
name = "idx_billing_plans_enabled_sort"
|
||||
columns = ["enabled", "sort_order"]
|
||||
|
||||
[table.user_plan_entitlements]
|
||||
domain = "wallet_billing"
|
||||
order = 56
|
||||
primary_key = ["id"]
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "user_id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "plan_id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "payment_order_id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "status"
|
||||
type = "text"
|
||||
length = 64
|
||||
default = "active"
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "starts_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "expires_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "entitlements_snapshot"
|
||||
type = "json"
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "created_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.user_plan_entitlements.columns]]
|
||||
name = "updated_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.user_plan_entitlements.indexes]]
|
||||
name = "idx_user_plan_entitlements_user_active"
|
||||
columns = ["user_id", "status", "expires_at"]
|
||||
|
||||
[[table.user_plan_entitlements.indexes]]
|
||||
name = "idx_user_plan_entitlements_order"
|
||||
columns = ["payment_order_id"]
|
||||
|
||||
[table.entitlement_usage_ledgers]
|
||||
domain = "wallet_billing"
|
||||
order = 57
|
||||
primary_key = ["id"]
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "user_entitlement_id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "user_id"
|
||||
type = "text_id"
|
||||
length = 64
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "request_id"
|
||||
type = "text"
|
||||
length = 128
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "amount_usd"
|
||||
type = "float64"
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "balance_before"
|
||||
type = "float64"
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "balance_after"
|
||||
type = "float64"
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "usage_date"
|
||||
type = "text"
|
||||
length = 16
|
||||
|
||||
[[table.entitlement_usage_ledgers.columns]]
|
||||
name = "created_at"
|
||||
type = "unix_seconds"
|
||||
|
||||
[[table.entitlement_usage_ledgers.uniques]]
|
||||
name = "uq_entitlement_usage_request"
|
||||
columns = ["user_entitlement_id", "request_id"]
|
||||
|
||||
[[table.entitlement_usage_ledgers.indexes]]
|
||||
name = "idx_entitlement_usage_user_date"
|
||||
columns = ["user_id", "usage_date"]
|
||||
|
||||
[[table.payment_callbacks.indexes]]
|
||||
name = "idx_payment_callbacks_order"
|
||||
columns = ["order_no"]
|
||||
|
||||
Reference in New Issue
Block a user