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:
@@ -0,0 +1,79 @@
|
||||
ALTER TABLE payment_orders
|
||||
ADD COLUMN payment_provider VARCHAR(64),
|
||||
ADD COLUMN payment_channel VARCHAR(64),
|
||||
ADD COLUMN order_kind VARCHAR(64) NOT NULL DEFAULT 'wallet_recharge',
|
||||
ADD COLUMN product_id VARCHAR(64),
|
||||
ADD COLUMN product_snapshot TEXT,
|
||||
ADD COLUMN fulfillment_status VARCHAR(64) NOT NULL DEFAULT 'pending',
|
||||
ADD COLUMN fulfillment_error TEXT;
|
||||
|
||||
CREATE INDEX idx_payment_orders_kind_status
|
||||
ON payment_orders (order_kind, status);
|
||||
CREATE INDEX idx_payment_orders_product
|
||||
ON payment_orders (product_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_gateway_configs (
|
||||
provider VARCHAR(64) PRIMARY KEY,
|
||||
enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
endpoint_url VARCHAR(512) NOT NULL,
|
||||
callback_base_url VARCHAR(512),
|
||||
merchant_id VARCHAR(128) NOT NULL,
|
||||
merchant_key_encrypted TEXT,
|
||||
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 TEXT,
|
||||
created_at BIGINT NOT NULL,
|
||||
updated_at BIGINT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS billing_plans (
|
||||
id VARCHAR(64) PRIMARY KEY,
|
||||
title VARCHAR(128) NOT NULL,
|
||||
description TEXT,
|
||||
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 BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
sort_order BIGINT NOT NULL DEFAULT 0,
|
||||
max_active_per_user BIGINT NOT NULL DEFAULT 1,
|
||||
entitlements_json TEXT NOT NULL,
|
||||
created_at BIGINT NOT NULL,
|
||||
updated_at BIGINT NOT NULL,
|
||||
KEY idx_billing_plans_enabled_sort (enabled, sort_order)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_plan_entitlements (
|
||||
id VARCHAR(64) PRIMARY KEY,
|
||||
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 TEXT NOT NULL,
|
||||
created_at BIGINT NOT NULL,
|
||||
updated_at BIGINT NOT NULL,
|
||||
KEY idx_user_plan_entitlements_user_active (user_id, status, expires_at),
|
||||
KEY idx_user_plan_entitlements_order (payment_order_id),
|
||||
CONSTRAINT user_plan_entitlements_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
CONSTRAINT user_plan_entitlements_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES billing_plans(id) ON DELETE RESTRICT,
|
||||
CONSTRAINT user_plan_entitlements_payment_order_id_fkey FOREIGN KEY (payment_order_id) REFERENCES payment_orders(id) ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS entitlement_usage_ledgers (
|
||||
id VARCHAR(64) PRIMARY KEY,
|
||||
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,
|
||||
UNIQUE KEY uq_entitlement_usage_request (user_entitlement_id, request_id),
|
||||
KEY idx_entitlement_usage_user_date (user_id, usage_date),
|
||||
CONSTRAINT entitlement_usage_ledgers_entitlement_fkey FOREIGN KEY (user_entitlement_id) REFERENCES user_plan_entitlements(id) ON DELETE CASCADE,
|
||||
CONSTRAINT entitlement_usage_ledgers_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE billing_plans
|
||||
ADD COLUMN purchase_limit_scope VARCHAR(32) NOT NULL DEFAULT 'active_period';
|
||||
@@ -0,0 +1,81 @@
|
||||
ALTER TABLE public.payment_orders
|
||||
ADD COLUMN payment_provider character varying(64),
|
||||
ADD COLUMN payment_channel character varying(64),
|
||||
ADD COLUMN order_kind character varying(64) NOT NULL DEFAULT 'wallet_recharge',
|
||||
ADD COLUMN product_id character varying(64),
|
||||
ADD COLUMN product_snapshot jsonb,
|
||||
ADD COLUMN fulfillment_status character varying(64) NOT NULL DEFAULT 'pending',
|
||||
ADD COLUMN fulfillment_error text;
|
||||
|
||||
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) PRIMARY KEY,
|
||||
enabled boolean NOT NULL DEFAULT false,
|
||||
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) NOT NULL DEFAULT 'CNY',
|
||||
usd_exchange_rate numeric(18,8) NOT NULL DEFAULT 7.2,
|
||||
min_recharge_usd numeric(20,8) NOT NULL DEFAULT 1,
|
||||
channels_json jsonb,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.billing_plans (
|
||||
id character varying(64) PRIMARY KEY,
|
||||
title character varying(128) NOT NULL,
|
||||
description text,
|
||||
price_amount numeric(20,8) NOT NULL,
|
||||
price_currency character varying(16) NOT NULL DEFAULT 'CNY',
|
||||
duration_unit character varying(32) NOT NULL,
|
||||
duration_value bigint NOT NULL,
|
||||
enabled boolean NOT NULL DEFAULT true,
|
||||
sort_order bigint NOT NULL DEFAULT 0,
|
||||
max_active_per_user bigint NOT NULL DEFAULT 1,
|
||||
entitlements_json jsonb NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
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) PRIMARY KEY,
|
||||
user_id character varying(64) NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
plan_id character varying(64) NOT NULL REFERENCES public.billing_plans(id) ON DELETE RESTRICT,
|
||||
payment_order_id character varying(64) NOT NULL REFERENCES public.payment_orders(id) ON DELETE RESTRICT,
|
||||
status character varying(64) NOT NULL DEFAULT 'active',
|
||||
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
|
||||
);
|
||||
|
||||
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) PRIMARY KEY,
|
||||
user_entitlement_id character varying(64) NOT NULL REFERENCES public.user_plan_entitlements(id) ON DELETE CASCADE,
|
||||
user_id character varying(64) NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
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,
|
||||
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);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE public.billing_plans
|
||||
ADD COLUMN IF NOT EXISTS purchase_limit_scope character varying(32) NOT NULL DEFAULT 'active_period';
|
||||
@@ -0,0 +1,85 @@
|
||||
ALTER TABLE payment_orders ADD COLUMN payment_provider TEXT;
|
||||
ALTER TABLE payment_orders ADD COLUMN payment_channel TEXT;
|
||||
ALTER TABLE payment_orders ADD COLUMN order_kind TEXT NOT NULL DEFAULT 'wallet_recharge';
|
||||
ALTER TABLE payment_orders ADD COLUMN product_id TEXT;
|
||||
ALTER TABLE payment_orders ADD COLUMN product_snapshot TEXT;
|
||||
ALTER TABLE payment_orders ADD COLUMN fulfillment_status TEXT NOT NULL DEFAULT 'pending';
|
||||
ALTER TABLE payment_orders ADD COLUMN fulfillment_error TEXT;
|
||||
|
||||
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,
|
||||
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 billing_plans (
|
||||
id TEXT PRIMARY KEY,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(plan_id) REFERENCES billing_plans(id) ON DELETE RESTRICT,
|
||||
FOREIGN KEY(payment_order_id) REFERENCES payment_orders(id) ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
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,
|
||||
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),
|
||||
FOREIGN KEY(user_entitlement_id) REFERENCES user_plan_entitlements(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_entitlement_usage_user_date
|
||||
ON entitlement_usage_ledgers (user_id, usage_date);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE billing_plans
|
||||
ADD COLUMN purchase_limit_scope TEXT NOT NULL DEFAULT 'active_period';
|
||||
Reference in New Issue
Block a user