ALTER TABLE qipai_payments ADD COLUMN platform_app_id BIGINT UNSIGNED NULL AFTER tenant_id, ADD COLUMN store_id BIGINT UNSIGNED NULL AFTER order_id, ADD COLUMN provider VARCHAR(32) NOT NULL DEFAULT 'WECHAT' AFTER channel, ADD COLUMN client_request_id VARCHAR(128) NULL AFTER provider, ADD COLUMN currency CHAR(3) NOT NULL DEFAULT 'CNY' AFTER amount_cents, ADD COLUMN provider_payment_id VARCHAR(128) NULL AFTER currency, ADD COLUMN failed_at DATETIME(3) NULL AFTER paid_at, ADD COLUMN failure_code VARCHAR(64) NOT NULL DEFAULT '' AFTER failed_at; UPDATE qipai_payments p INNER JOIN qipai_orders o ON o.tenant_id = p.tenant_id AND o.id = p.order_id SET p.store_id = o.store_id, p.client_request_id = CONCAT('legacy-payment-', p.id) WHERE p.store_id IS NULL OR p.client_request_id IS NULL; ALTER TABLE qipai_payments MODIFY COLUMN store_id BIGINT UNSIGNED NOT NULL, MODIFY COLUMN client_request_id VARCHAR(128) NOT NULL, ADD CONSTRAINT fk_qipai_payments_platform_app FOREIGN KEY (platform_app_id) REFERENCES qipai_platform_apps(id), ADD CONSTRAINT fk_qipai_payments_store FOREIGN KEY (store_id) REFERENCES qipai_stores(id), ADD UNIQUE KEY uq_qipai_payments_client_request (tenant_id, client_request_id), ADD UNIQUE KEY uq_qipai_payments_provider_id (tenant_id, provider, provider_payment_id); CREATE TABLE IF NOT EXISTS qipai_payment_attempts ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, tenant_id BIGINT UNSIGNED NOT NULL, payment_id BIGINT UNSIGNED NOT NULL, attempt_no INT UNSIGNED NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'CREATED', request_payload JSON NOT NULL, response_payload JSON NULL, error_code VARCHAR(64) NOT NULL DEFAULT '', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), completed_at DATETIME(3) NULL, CONSTRAINT fk_qipai_payment_attempt_tenant FOREIGN KEY (tenant_id) REFERENCES qipai_tenants(id), CONSTRAINT fk_qipai_payment_attempt_payment FOREIGN KEY (payment_id) REFERENCES qipai_payments(id), UNIQUE KEY uq_qipai_payment_attempt_no (tenant_id, payment_id, attempt_no), KEY idx_qipai_payment_attempt_status (tenant_id, status, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS qipai_payment_callbacks ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, tenant_id BIGINT UNSIGNED NOT NULL, payment_id BIGINT UNSIGNED NULL, provider VARCHAR(32) NOT NULL, callback_id VARCHAR(128) NOT NULL, callback_type VARCHAR(32) NOT NULL, verified TINYINT(1) NOT NULL DEFAULT 0, processing_status VARCHAR(32) NOT NULL DEFAULT 'RECEIVED', payload JSON NOT NULL, error_code VARCHAR(64) NOT NULL DEFAULT '', received_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), processed_at DATETIME(3) NULL, CONSTRAINT fk_qipai_payment_callback_tenant FOREIGN KEY (tenant_id) REFERENCES qipai_tenants(id), CONSTRAINT fk_qipai_payment_callback_payment FOREIGN KEY (payment_id) REFERENCES qipai_payments(id), UNIQUE KEY uq_qipai_payment_callback_provider (tenant_id, provider, callback_id), KEY idx_qipai_payment_callback_status (tenant_id, processing_status, received_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS qipai_refunds ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, tenant_id BIGINT UNSIGNED NOT NULL, payment_id BIGINT UNSIGNED NOT NULL, order_id BIGINT UNSIGNED NOT NULL, refund_no VARCHAR(64) NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'PENDING', amount_cents INT UNSIGNED NOT NULL, reason VARCHAR(512) NOT NULL DEFAULT '', provider_refund_id VARCHAR(128) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), completed_at DATETIME(3) NULL, CONSTRAINT fk_qipai_refund_tenant FOREIGN KEY (tenant_id) REFERENCES qipai_tenants(id), CONSTRAINT fk_qipai_refund_payment FOREIGN KEY (payment_id) REFERENCES qipai_payments(id), CONSTRAINT fk_qipai_refund_order FOREIGN KEY (order_id) REFERENCES qipai_orders(id), UNIQUE KEY uq_qipai_refund_no (tenant_id, refund_no), UNIQUE KEY uq_qipai_refund_provider (tenant_id, provider_refund_id), KEY idx_qipai_refund_status (tenant_id, status, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS qipai_profit_shares ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, tenant_id BIGINT UNSIGNED NOT NULL, payment_id BIGINT UNSIGNED NOT NULL, order_id BIGINT UNSIGNED NOT NULL, share_no VARCHAR(64) NOT NULL, receiver_type VARCHAR(32) NOT NULL, receiver_ref VARCHAR(128) NOT NULL, amount_cents INT UNSIGNED NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'PENDING', provider_share_id VARCHAR(128) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), completed_at DATETIME(3) NULL, CONSTRAINT fk_qipai_profit_share_tenant FOREIGN KEY (tenant_id) REFERENCES qipai_tenants(id), CONSTRAINT fk_qipai_profit_share_payment FOREIGN KEY (payment_id) REFERENCES qipai_payments(id), CONSTRAINT fk_qipai_profit_share_order FOREIGN KEY (order_id) REFERENCES qipai_orders(id), UNIQUE KEY uq_qipai_profit_share_no (tenant_id, share_no), KEY idx_qipai_profit_share_status (tenant_id, status, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS qipai_payment_configs ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, tenant_id BIGINT UNSIGNED NULL, platform_app_id BIGINT UNSIGNED NULL, store_id BIGINT UNSIGNED NULL, provider VARCHAR(32) NOT NULL, scope_key VARCHAR(255) NOT NULL, enabled TINYINT(1) NOT NULL DEFAULT 1, credential_ref VARCHAR(255) NOT NULL DEFAULT '', settings JSON NOT NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), CONSTRAINT fk_qipai_payment_config_tenant FOREIGN KEY (tenant_id) REFERENCES qipai_tenants(id), CONSTRAINT fk_qipai_payment_config_app FOREIGN KEY (platform_app_id) REFERENCES qipai_platform_apps(id), CONSTRAINT fk_qipai_payment_config_store FOREIGN KEY (store_id) REFERENCES qipai_stores(id), UNIQUE KEY uq_qipai_payment_config_scope (provider, scope_key), KEY idx_qipai_payment_config_resolution (provider, enabled, tenant_id, platform_app_id, store_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT IGNORE INTO qipai_schema_migrations (version, name) VALUES ('2026062015', 'm05a_payment_domain');