CREATE TABLE IF NOT EXISTS sms_verification_codes ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, phone_hash BINARY(32) NOT NULL, scene VARCHAR(30) NOT NULL, code_hash BINARY(32) NOT NULL, expires_at DATETIME(3) NOT NULL, used_at DATETIME(3) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY (id), KEY idx_sms_phone_scene_created (phone_hash, scene, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO system_configs (config_key, config_value, value_type, description) VALUES ('sms.enabled', 'true', 'boolean', '是否启用短信服务'), ('sms.provider', 'debug', 'string', '短信提供商:debug 或 webhook'), ('sms.sign_name', '星遇社交', 'string', '短信签名'), ('sms.template_register', 'REGISTER', 'string', '注册验证码模板 ID'), ('sms.template_login', 'LOGIN', 'string', '登录验证码模板 ID'), ('sms.template_reset', 'RESET', 'string', '找回密码模板 ID'), ('sms.webhook_url', '', 'string', '短信网关 Webhook 地址'), ('sms.webhook_token', '', 'secret', '短信网关鉴权令牌'), ('sms.debug_code', '123456', 'secret', '本地调试验证码'), ('sms.expire_seconds', '300', 'number', '验证码有效期(秒)'), ('payment.mode', 'sandbox', 'string', '支付模式:sandbox 或 live'), ('payment.alipay.enabled', 'true', 'boolean', '是否启用支付宝'), ('payment.alipay.app_id', '', 'string', '支付宝应用 APPID'), ('payment.alipay.private_key', '', 'secret', '支付宝应用私钥'), ('payment.alipay.public_key', '', 'secret', '支付宝公钥'), ('payment.alipay.notify_url', '', 'string', '支付宝异步通知地址'), ('payment.wechat.enabled', 'true', 'boolean', '是否启用微信支付'), ('payment.wechat.app_id', '', 'string', '微信支付 AppID'), ('payment.wechat.mch_id', '', 'string', '微信支付商户号'), ('payment.wechat.api_v3_key', '', 'secret', '微信支付 APIv3 密钥'), ('payment.wechat.private_key', '', 'secret', '微信支付商户私钥'), ('payment.wechat.serial_no', '', 'string', '微信支付证书序列号'), ('payment.wechat.notify_url', '', 'string', '微信支付回调地址') ON DUPLICATE KEY UPDATE description = VALUES(description), value_type = VALUES(value_type);